[Poi2000]公共串
Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 1386 Solved: 620
[Submit][Status][Discuss]
Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
Output
仅一行,一个整数,最长公共子串的长度。
Sample Input
3
abcb
bca
acbc
abcb
bca
acbc
Sample Output
2
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 ",ans); 80 }