【bzoj2946】[Poi2000]公共串 后缀自动机

[Poi2000]公共串

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1386  Solved: 620
[Submit][Status][Discuss]

Description

 
       给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l        读入单词
l        计算最长公共子串的长度
l        输出结果
 

Input

 
文件的第一行是整数 n1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000
 

Output

仅一行,一个整数,最长公共子串的长度。
 

Sample Input

3
abcb
bca
acbc

Sample Output

HINT

后缀自动机

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 
 7 #define N 2007
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 
17 int n;
18 char ch[N];
19 
20 struct SAM
21 {
22     int cnt,last;
23     int fa[4005],a[4005][27],mx[4005],len[4005],ans[4005];
24     int v[4005],q[4005];
25     SAM(){last=++cnt;}
26     void extend(int c)
27     {
28         int p=last,np=last=++cnt;mx[np]=mx[p]+1;
29         while(!a[p][c]&&p)a[p][c]=np,p=fa[p];
30         if(!p)fa[np]=1;
31         else 
32         {
33             int q=a[p][c];
34             if(mx[p]+1==mx[q])fa[np]=q;
35             else 
36             {
37                 int nq=++cnt;mx[nq]=mx[p]+1;
38                 memcpy(a[nq],a[q],sizeof(a[q]));
39                 fa[nq]=fa[q];
40                 fa[np]=fa[q]=nq;
41                 while(a[p][c]==q)a[p][c]=nq,p=fa[p];
42             }
43         }
44     }
45     void pre()
46     {
47         for(int i=1;i<=cnt;i++)ans[i]=mx[i];
48         for(int i=1;i<=cnt;i++)v[mx[i]]++;
49         for(int i=1;i<=cnt;i++)v[i]+=v[i-1];
50         for(int i=cnt;i;i--)q[v[mx[i]]--]=i;
51     }
52     void solve()
53     {
54         scanf("%s",ch+1);
55         memset(len,0,sizeof(len));
56         int l=strlen(ch+1),p=1,tmp=0;
57         for(int i=1;i<=l;i++)
58         {
59             int c=ch[i]-'a';
60             while(!a[p][c]&&p)p=fa[p];
61             if(p==0)p=1,tmp=0;
62             else tmp=min(tmp,mx[p])+1,p=a[p][c];
63             len[p]=max(len[p],tmp);
64         }
65         for(int i=cnt;i;i--)len[fa[q[i]]]=max(len[fa[q[i]]],len[q[i]]);
66         for(int i=1;i<=cnt;i++)ans[i]=min(ans[i],len[i]);
67     }
68 }sam;
69 int main()
70 {
71     n=read();scanf("%s",ch+1);
72     int l=strlen(ch+1);
73     for(int i=1;i<=l;i++)sam.extend(ch[i]-'a');
74     sam.pre();
75     for(int i=1;i<n;i++)sam.solve();
76     int ans=0;
77     for(int i=1;i<=sam.cnt;i++)
78         ans=max(ans,sam.ans[i]);
79     printf("%d\n",ans);
80 }

 

posted @ 2018-01-15 10:16  Kaiser-  阅读(186)  评论(0编辑  收藏  举报