【SPOJ】Longest Common Substring
阿新 • • 發佈:2018-12-30
【SPOJ】Longest Common Substring
求兩個字串的最長公共子串
對一個串建好字尾自動機然後暴力跑一下 廢話
講一下怎麼跑吧
從第一個字元開始遍歷,遍歷不到了再沿著\(parents\)走看能否找到出路,走到某個點時,統計一下走過了多少點然後更新答案
來說說這樣做的正確性:
遍歷是肯定的, PAM 從根節點出發的任意路徑都表示一個子串
沿著\(parents\)邊往後走,保證貪心情況下維護最長公共子串尋找出路
注意這裡是統計走過了多少點更新答案,不能直接通過\(len\)更新答案
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; typedef long long LL; const LL maxn=600000; LL nod,last,n,T; LL len[maxn],fail[maxn],son[maxn][26]; char s[maxn]; inline void Insert(LL c){ LL np=++nod,p=last; len[np]=len[p]+1; last=np; while(p&&!son[p][c]){ son[p][c]=np, p=fail[p]; } if(!p) fail[np]=1; else{ LL q=son[p][c]; if(len[q]==len[p]+1) fail[np]=q; else{ LL nq=++nod; len[nq]=len[p]+1; fail[nq]=fail[q]; memcpy(son[nq],son[q],sizeof(son[q])); fail[np]=fail[q]=nq; while(p&&son[p][c]==q){ son[p][c]=nq, p=fail[p]; } } } } int main(){ nod=last=1; scanf(" %s",s); LL Len=strlen(s); for(LL i=0;i<Len;++i) Insert(s[i]-'a'); scanf(" %s",s); LL ans=0,now=1,cnt=0; Len=strlen(s); for(LL i=0;i<Len;++i){ LL c=s[i]-'a'; if(son[now][c]) ++cnt, now=son[now][c]; else{ while(now&&!son[now][c]) now=fail[now]; if(!now) cnt=0, now=1; else cnt=len[now]+1, now=son[now][c]; } ans=max(ans,cnt); } printf("%lld\n",ans); return 0; }/* fjewiofejhiofjmwopejeugfzjkjnfoakweldnfmoierhguiewkjfkowejrfoiwejsfd jwierhdwuiek,dedjfkz[pjeowrfhuqigrfwerljfiuekdfkcdfheosf */