BZOJ2946: [Poi2000]公共串
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2946
先用第一个字符串建后缀自动机,每个节点记录一下每个字符串与之匹配的最大值,那么每个节点对答案的贡献就是所记录的最大值的最小值,把所有刚刚说的最小值取max就是答案了。绕晕了。语文不好真是日了狗。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define inf 1<<30 5 #define maxn 2005 6 using namespace std; 7 char s[maxn]; 8 int tot,last,root,sum,n,m,pps,v[maxn*2],q[maxn*2]; 9 struct fuck{int par,go[26],val,ans[6];}suf[maxn*2]; 10 int newnode(int x){suf[++tot].val=suf[x].val+1;return tot;} 11 void extend(int x){ 12 int p=last,np=newnode(p); 13 while(p&&suf[p].go[x]==0) suf[p].go[x]=np,p=suf[p].par; 14 if(p==0) suf[np].par=root; 15 else{ 16 int q=suf[p].go[x]; 17 if(suf[q].val==suf[p].val+1) suf[np].par=q; 18 else{ 19 int nq=newnode(p); 20 memcpy(suf[nq].go,suf[q].go,sizeof(suf[q].go)); 21 suf[nq].par=suf[q].par; 22 suf[q].par=suf[np].par=nq; 23 while(p&&suf[p].go[x]==q) suf[p].go[x]=nq,p=suf[p].par; 24 } 25 } 26 last=np; 27 } 28 int main(){ 29 last=tot=root=1; 30 scanf("%d\n",&n); scanf("%s",s); m=strlen(s); 31 for(int i=0;i<m;i++) extend(s[i]-'a'); 32 for(int i=1;i<=tot;i++) suf[i].ans[0]=suf[i].val; 33 for(int i=1;i<=tot;i++) v[suf[i].val]++; 34 for(int i=1;i<=tot;i++) v[i]+=v[i-1]; 35 for(int i=tot;i;i--) q[v[suf[i].val]--]=i; 36 for(int j=2;j<=n;j++){ 37 scanf("%s",s); m=strlen(s); sum=0; 38 for(int i=0,pp=root;i<m;i++){ 39 int f=s[i]-'a'; 40 while(pp&&!suf[pp].go[f]) pp=suf[pp].par; 41 if(pp) sum=min(sum,suf[pp].val)+1,pp=suf[pp].go[f]; 42 else sum=0,pp=root; 43 suf[pp].ans[j]=max(suf[pp].ans[j],sum); 44 } 45 for(int i=tot;i;i--) suf[suf[q[i]].par].ans[j]=max(suf[suf[q[i]].par].ans[j],suf[q[i]].ans[j]); 46 for(int i=1;i<=tot;i++) suf[i].ans[0]=min(suf[i].ans[0],suf[i].ans[j]); 47 } 48 pps=0; 49 for(int i=1;i<=tot;i++) pps=max(pps,suf[i].ans[0]); 50 printf("%d\n",pps); 51 return 0; 52 }