[bzoj2774]Long Long Message

题目大意:求两个字符串的最长公共子串。

字符串界三大神器:Hash、自动机、平衡树。

建立一个后缀自动机,然后在其上跑另一个串,如果可以拓展那么就拓展,否则就跳到失配边,然后与此同时更新答案。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <string>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <complex>
11 #include <set>
12 using namespace std;
13 
14 const int N=500000;
15 
16 int ch[N][30],len[N],pre[N];
17 int p,np,q,nq,last=1,tot=1;
18 char a[N],b[N];;
19 int ans;
20 int nd(int l){return len[++tot]=l,tot;}
21 void add(int v){
22     last=np=nd(len[p=last]+1);
23     while(p&&!ch[p][v])ch[p][v]=np,p=pre[p];
24     pre[np]=1;
25     if(p){
26         pre[np]=q=ch[p][v];
27         if(len[p]+1!=len[q]){
28             nq=nd(len[p]+1),pre[nq]=pre[q],pre[q]=pre[np]=nq;
29             memcpy(ch[nq],ch[q],sizeof ch[q]);
30             while(p&&ch[p][v]==q)ch[p][v]=nq,p=pre[p];
31         }
32     }
33 }
34 
35 int main(){
36     scanf("%s%s",a,b);
37     for(int i=0;a[i];i++)add(a[i]-'a');
38     int p=last,tot=0;
39     for(int i=0;b[i];i++){
40         int v=b[i]-'a';
41         if(ch[p][v])p=ch[p][v],tot++;
42         else{
43             while(p&&!ch[p][v])p=pre[p];
44             if(p)tot=len[p]+1,p=ch[p][v];else p=1,tot=0;
45         }
46         ans=max(ans,tot);
47     }
48     printf("%d\n",ans);
49 }
View Code

 

posted @ 2017-02-25 22:57  KingSann  阅读(142)  评论(0)    收藏  举报