http://www.lydsy.com/JudgeOnline/problem.php?id=2946
题意:给n个串,求最大公共子串。(1<=n<=5,每个串长度<=2000)
#include <bits/stdc++.h> using namespace std; const int N=2005<<1; struct sam { int cnt, root, last, l[N], c[N][26], f[N], p[N], mx[N], mxl[N]; sam() { cnt=0; root=last=++cnt; } void add(int x) { int now=last, a=++cnt; last=a; l[a]=l[now]+1; for(; now && !c[now][x]; now=f[now]) c[now][x]=a; if(!now) { f[a]=root; return; } int q=c[now][x]; if(l[q]==l[now]+1) { f[a]=q; return; } int b=++cnt; memcpy(c[b], c[q], sizeof c[q]); l[b]=l[now]+1; f[b]=f[q]; f[q]=f[a]=b; for(; now && c[now][x]==q; now=f[now]) c[now][x]=b; } void build(char *s) { int len=strlen(s); for(int i=0; i<len; ++i) add(s[i]-‘a‘); for(int i=1; i<=cnt; ++i) mx[l[i]]++; for(int i=1; i<=len; ++i) mx[i]+=mx[i-1]; for(int i=1; i<=cnt; ++i) p[mx[l[i]]--]=i; for(int i=1; i<=cnt; ++i) mx[i]=l[i]; } void find(char *s) { int x, now=root, t=0, len=strlen(s); for(int i=0; i<len; ++i) { x=s[i]-‘a‘; if(c[now][x]) ++t, now=c[now][x]; else { while(now && !c[now][x]) now=f[now]; if(!now) t=0, now=root; else t=l[now]+1, now=c[now][x]; } mxl[now]=max(mxl[now], t); } for(int i=cnt; i; --i) { x=p[i]; mx[x]=min(mx[x], mxl[x]); if(mxl[x] && f[x]) mxl[f[x]]=l[f[x]]; mxl[x]=0; } } int getans() { int ret=0; for(int i=1; i<=cnt; ++i) ret=max(ret, mx[i]); return ret; } }solver; char s[N]; int main() { int n; scanf("%d", &n); scanf("%s", s); solver.build(s); --n; while(n--) scanf("%s", s), solver.find(s); printf("%d\n", solver.getans()); return 0; }
复习了下sam....
时间: 2024-11-03 21:31:32