• SP1812 LCS2


    传送门

    前一题的加强版……求10个串的最长公共子串的长度。

    OI-Wiki上的解法我没看懂……

    朴素的想法还是对第一个串建立SAM,之后把后面的串不断地在上面匹配,对于每一个状态记录匹配最小值,所有状态取最大值。不过这样是会WA的……

    为啥呢?因为我们是对于每个状态取最小,然后最后在算答案的时候取最大,但是这样会有问题。对于每一个节点,我们需要取其子树中最大的答案来作为结果,因为我们统计答案的时候是取最小匹配中的最大值,一个串在互相匹配的时候,可能一个位置本来有一个很长的匹配,但是却在后面的匹配中答案被覆盖了。如果一个点能被匹配那么其parent树上的祖先也能,所以要对子树取最大,然后和自身长度比较取比较小的值。这样才能保证答案是正确的。

    看一下代码。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(register int i = a;i <= n;i++)
    #define per(i,n,a) for(register int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 10000005;
    const int INF = 2147483647;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
        while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
        return ans * op;
    }
    
    char s[M],t[M];
    int n,m,maxn[M<<1],minn[M<<1],a[M<<1],c[M<<1],ans,pos;
    
    struct Suffix
    {
        int last,cnt,ch[M<<1][26],fa[M<<1],l[M<<1];
        void extend(int c)
        {
            int p = last,np = ++cnt;
            last = cnt,l[np] = l[p] + 1;
            while(p && !ch[p][c]) ch[p][c] = np,p = fa[p];
            if(!p) {fa[np] = 1;return;}
            int q = ch[p][c];
            if(l[q] == l[p] + 1) fa[np] = q;
            else
            {
                int nq = ++cnt;
                l[nq] = l[p] + 1,memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq] = fa[q],fa[q] = fa[np] = nq;
                while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
            }
        }
        void cal()
        {
            rep(i,1,cnt) c[l[i]]++;
            rep(i,1,cnt) c[i] += c[i-1];
            rep(i,1,cnt) a[c[l[i]]--] = i;
        }
        void match(char *b)
        {
            int v = 1,len = 0;
            rep(i,0,m-1)
            {
                int c = b[i] - 'a';
                while(!ch[v][c] && v != 1) v = fa[v],len = l[v];
                if(ch[v][c]) v = ch[v][c],len++,maxn[v] = max(maxn[v],len);
                //printf("#%d
    ",maxn[v]);
            }
            per(i,cnt,1)
            {
                int p = a[i];
                //printf("!%d %d
    ",maxn[p],p);
                maxn[fa[p]] = max(maxn[fa[p]],min(maxn[p],l[fa[p]]));
                minn[p] = min(minn[p],maxn[p]),maxn[p] = 0;
            }
        }
    }SAM;
    
    int main()
    {
        scanf("%s",s+1),n = strlen(s+1);
        SAM.last = SAM.cnt = 1;
        rep(i,1,n) SAM.extend(s[i] - 'a');
        SAM.cal(),memset(minn,0x3f,sizeof(minn));
        while(scanf("%s",t+1) != EOF) m = strlen(t+1),SAM.match(t+1);
        //printf("%d
    ",ans);
        rep(i,1,SAM.cnt) ans = max(ans,minn[i]);//printf("%d
    ",minn[i]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    关键字--super
    JSP学习笔记3--指令元素
    JSP学习笔记2--JSP基本元素
    力扣233.数字1出现的次数
    JSP学习笔记1
    继承
    Cocos2dx-Lua中Sprite精灵的3种创建方法
    cocos2dx Action动作 (3)CCSkewTo、CCSkewBy
    cocos2dx Action动作解析(2)
    cocos2dx Action动作解析(1)
  • 原文地址:https://www.cnblogs.com/captain1/p/10261142.html
Copyright © 2020-2023  润新知