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;
}

 

posted @ 2018-12-12 14:51  Zinn  阅读(125)  评论(0编辑  收藏  举报