bzoj 2946 公共串 —— 后缀自动机

时间:2022-07-15 22:53:34

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2946

建出 n-1 个后缀自动机一起跑呗。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=;
int n,lst[],cnt[],fa[][xn<<],l[][xn<<],go[][xn<<][],nw[];//<<1!!
char s[][xn];
void add(int t,int w)
{
int p=lst[t],np=++cnt[t]; lst[t]=np; l[t][np]=l[t][p]+;
for(;p&&!go[t][p][w];p=fa[t][p])go[t][p][w]=np;
if(!p)fa[t][np]=;
else
{
int q=go[t][p][w];
if(l[t][q]==l[t][p]+)fa[t][np]=q;
else
{
int nq=++cnt[t]; l[t][nq]=l[t][p]+;
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]=; cnt[t]=;
int len=strlen(s[t]+);
for(int i=;i<=len;i++)add(t,s[t][i]-'a');
}
bool trans(int j)
{
int w=s[n][j]-'a';
for(int i=;i<n;i++)
{
if(!go[i][nw[i]][w])return ;
nw[i]=go[i][nw[i]][w];
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",s[i]+);
if(i<n)build(i);
}
int ans=,len=strlen(s[n]+);
for(int i=,j;i<=len;i++)
{
for(j=;j<n;j++)nw[j]=;
for(j=i;j<=len;j++)if(!trans(j))break;
ans=max(ans,j-i);
}
printf("%d\n",ans);
return ;
}