SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS

LCS2 - Longest Common Substring II

no tags 

 

A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

Input

The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn't exist, print "0" instead.

Example

Input:
alsdfkjfjkdsal
fdjskalajfkdsla
aaaajfaaaa

Output:
2

Notice: new testcases added

 

 

题意:

  求多个串的最长公共字串

题解:

  将第一个串建立后缀自动机

  根据拓扑排序更新每个状态节点下所能向前延伸的长度,每次匹配一个串都更新即可

  是不是很模糊

#include <bits/stdc++.h>
inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
using namespace std;

const int N = 3e5+7;

const long long mod = 1000000007;

int isPlus[N * 2],endpos[N * 2];int d[N * 2];
int tot,slink[2*N],trans[2*N][28],minlen[2*N],maxlen[2*N],pre;
int newstate(int _maxlen,int _minlen,int* _trans,int _slink){
    maxlen[++tot]=_maxlen;minlen[tot]=_minlen;
    slink[tot]=_slink;
    if(_trans)for(int i=0;i<26;i++)trans[tot][i]=_trans[i],d[_trans[i]]+=1;
    return tot;
}
int add_char(char ch,int u){
    int c=ch-'a',v=u;
    int z=newstate(maxlen[u]+1,-1,NULL,0);
    isPlus[z] = 1;
    while(v&&!trans[v][c]){trans[v][c]=z;d[z]+=1;v=slink[v];}
    if(!v){ minlen[z]=1;slink[z]=1;return z;}
    int x=trans[v][c];
    if(maxlen[v]+1==maxlen[x]){slink[z]=x;minlen[z]=maxlen[x]+1;return z;}
    int y=newstate(maxlen[v]+1,-1,trans[x],slink[x]);
    slink[z]=slink[x]=y;minlen[x]=minlen[z]=maxlen[y]+1;
    while(v&&trans[v][c]==x){trans[v][c]=y;d[x]--,d[y]++;v=slink[v];}
    minlen[y]=maxlen[slink[y]]+1;
    return z;
}
void init_sam() {
    for(int i = 1; i <= tot; ++i)
        for(int j = 0; j < 26; ++j) trans[i][j] = 0;
    pre = tot = 1;
}

int dp[N],ans,n,vis[N],cnt[N],pos[N];
char a[N];
int main() {
    int f = 1;
    while(scanf("%s",a)!=EOF) {
        n = strlen(a);
        if(f) {
            init_sam();
            for(int i = 0; i < n; ++i)
                pre = add_char(a[i],pre);
            f = 0;
            for(int i = 0; i <= n; ++i)cnt[i] = 0;
            for(int i = 2; i <= tot; ++i)cnt[maxlen[i]] += 1;
            for(int i = 1; i <= n; ++i)cnt[i]+=cnt[i-1];
            for(int i = tot; i >= 2; --i)pos[cnt[maxlen[i]]--] = i;
        }
        else
        {
            int now = 1,sum = 0;
            for(int i = 0; i < n; ++i)
            {
                if(trans[now][a[i]-'a']) {
                    sum++;
                    now = trans[now][a[i]-'a'];
                    dp[now] = max(dp[now],sum);
                }
                else {
                    while(now) {
                        now = slink[now];
                        if(trans[now][a[i]-'a']) break;
                    }
                    if(!now) now = 1,sum = 0;
                    else
                    {
                        sum = maxlen[now] + 1;
                        now = trans[now][a[i]-'a'];
                        dp[now] = max(dp[now],sum);
                    }
                }
            }
            for(int i = tot; i >= 2; --i) {
                int v = pos[i];
                maxlen[v] = min(maxlen[v],dp[v]);
                dp[slink[v]] = max(dp[slink[v]],dp[v]);
                dp[v] = 0;
            }
        }
    }
    int ans = 0;
    for(int i = 2; i <= tot; ++i) {
        ans = max(ans,maxlen[i]);
    }
    printf("%d\n",ans);
    return 0;
}
/*
aabbcd
babbefg
cdbbabb
*/

 

posted @ 2017-10-01 13:19  meekyan  阅读(648)  评论(0编辑  收藏  举报