codevs 3160 最长公共子串 后缀自动机
http://codevs.cn/problem/3160/
后缀自动机板子题,匹配的时候要注意如果到一个点失配向前匹配到一个点时,此时的tmp(当前匹配值)为t[j].len+1而不是t[t[j].sig[z]].len,想一下自动机的特质就可以明白了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 const int maxn=100010; 9 char ch1[maxn]={},ch2[maxn]={}; 10 int siz1,siz2; 11 struct nod{ 12 int sig[26]; 13 int f,len; 14 }t[maxn*2];int tot=1,la=1; 15 void add(int z){ 16 int x=++tot;int i=la; 17 t[x].len=t[la].len+1; 18 for(;i&&!t[i].sig[z];i=t[i].f) 19 t[i].sig[z]=x; 20 if(!i)t[x].f=1; 21 else{ 22 int p=t[i].sig[z]; 23 if(t[p].len==t[i].len+1)t[x].f=p; 24 else{ 25 int y=++tot; 26 t[y]=t[p];t[y].len=t[i].len+1; 27 t[x].f=t[p].f=y; 28 for(;i&&t[i].sig[z]==p;i=t[i].f){ 29 t[i].sig[z]=y; 30 } 31 } 32 } 33 la=x; 34 } 35 int main(){ 36 memset(t,0,sizeof(t)); 37 scanf("%s",ch1+1); 38 scanf("%s",ch2+1); 39 siz1=strlen(ch1+1); 40 siz2=strlen(ch2+1); 41 for(int i=1;i<=siz1;i++)add(int(ch1[i]-'a')); 42 int ans=0,j=1,tmp=0; 43 for(int i=1;i<=siz2;i++){ 44 int z=ch2[i]-'a'; 45 if(t[j].sig[z]){j=t[j].sig[z];tmp++;} 46 else{ 47 while(j&&!t[j].sig[z]) 48 j=t[j].f; 49 if(!j){j=1;tmp=0;} 50 else {tmp=t[j].len+1;j=t[j].sig[z];} 51 } 52 if(tmp>ans)ans=tmp; 53 }printf("%d\n",ans); 54 return 0; 55 }