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