1. 程式人生 > >codevs 3160 最長公共子串(SAM)

codevs 3160 最長公共子串(SAM)

namespace 父親 char register memcpy == pen bits esp

題解:

因為父親節點是第一個right集合不同的後綴

所以我們用ac自動機匹配的方法向下找,不符合了就往父親方向跳

時間復雜度O(n)

代碼:

#include <bits/stdc++.h>
#define ll long long
#define rint register int
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
using namespace std;
const int N=3e6;
char s[N],s1[N];
int size[N],len[N],ch[N][26]; int lst=1,node=1,t[N],a[N],fa[N],ans; void extend(int c) { int f=lst,p=++node; lst=p; len[p]=len[f]+1; size[p]=1; while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f]; if (!f) { fa[p]=1; return;}; int x=ch[f][c],y=++node; if (len[f]+1==len[x]) {fa[p]=x; node--;return
;}; len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y; memcpy(ch[y],ch[x],sizeof(ch[x])); while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f]; } void js() { int l=strlen(s1),now=1,t=0; rep(i,1,l) { int x=s1[i-1]-a; if (ch[now][x]) now=ch[now][x],++t; else {
while (now&&!ch[now][x]) now=fa[now]; if (!now) now=1,t=0; else t=len[now]+1,now=ch[now][x]; } ans=max(ans,t); } } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>s; int l=strlen(s); rep(i,1,l) extend(s[i-1]-a); cin>>s1; js(); cout<<ans<<endl; return 0; }

codevs 3160 最長公共子串(SAM)