codevs 3160 最长公共子串 后缀自动机

http://codevs.cn/problem/3160/

后缀自动机板子题,匹配的时候要注意如果到一个点失配向前匹配到一个点时,此时的tmp(当前匹配值)为t[j].len+1而不是t[t[j].sig[z]].len,想一下自动机的特质就可以明白了。

 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 }
View Code

 

posted @ 2018-03-12 18:03  鲸头鹳  阅读(120)  评论(0编辑  收藏  举报