bzoj 2946 公共串 —— 后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2946
建出 n-1 个后缀自动机一起跑呗。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const xn=2005; int n,lst[10],cnt[10],fa[10][xn<<1],l[10][xn<<1],go[10][xn<<1][30],nw[10];//<<1!! char s[10][xn]; void add(int t,int w) { int p=lst[t],np=++cnt[t]; lst[t]=np; l[t][np]=l[t][p]+1; for(;p&&!go[t][p][w];p=fa[t][p])go[t][p][w]=np; if(!p)fa[t][np]=1; else { int q=go[t][p][w]; if(l[t][q]==l[t][p]+1)fa[t][np]=q; else { int nq=++cnt[t]; l[t][nq]=l[t][p]+1; memcpy(go[t][nq],go[t][q],sizeof go[t][q]); fa[t][nq]=fa[t][q]; fa[t][q]=fa[t][np]=nq; for(;go[t][p][w]==q;p=fa[t][p])go[t][p][w]=nq; } } } void build(int t) { lst[t]=1; cnt[t]=1; int len=strlen(s[t]+1); for(int i=1;i<=len;i++)add(t,s[t][i]-'a'); } bool trans(int j) { int w=s[n][j]-'a'; for(int i=1;i<n;i++) { if(!go[i][nw[i]][w])return 0; nw[i]=go[i][nw[i]][w]; } return 1; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s[i]+1); if(i<n)build(i); } int ans=0,len=strlen(s[n]+1); for(int i=1,j;i<=len;i++) { for(j=1;j<n;j++)nw[j]=1; for(j=i;j<=len;j++)if(!trans(j))break; ans=max(ans,j-i); } printf("%d\n",ans); return 0; }