1. 程式人生 > >POJ - 1743 字尾自動機

POJ - 1743 字尾自動機

POJ - 1743

順著原字串找到所有葉子節點,然後自下而上更新,每個節點right的最左和最右,然後求出答案。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define PDD pair<double,double>
#define
ull unsigned long long using namespace std; const int N = 20000 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const int base = 87; int n; int s[N], a[N]; struct SuffixAutomaton { int last, cur, cnt, ch[N<<1
][175], id[N<<1], fa[N<<1], dis[N<<1], sz[N<<1], c[N]; int mx[N<<1], mn[N<<1]; SuffixAutomaton() {cur = cnt = 1;} void init() { for(int i = 1; i <= cnt; i++) { memset(ch[i], 0, sizeof(ch[i])); sz[i] = c[i] = dis[i] = fa[i] = 0
; } cur = cnt = 1; } void extend(int c, int id) { last = cur; cur = ++cnt; int p = last; dis[cur] = id; for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = cur; if(!p) fa[cur] = 1; else { int q = ch[p][c]; if(dis[q] == dis[p]+1) fa[cur] = q; else { int nt = ++cnt; dis[nt] = dis[p]+1; memcpy(ch[nt], ch[q], sizeof(ch[q])); fa[nt] = fa[q]; fa[q] = fa[cur] = nt; for(; ch[p][c]==q; p=fa[p]) ch[p][c] = nt; } } sz[cur] = 1; } void getSize(int n) { for(int i = 1; i <= cnt; i++) c[dis[i]]++; for(int i = 1; i <= n; i++) c[i] += c[i-1]; for(int i = cnt; i >= 1; i--) id[c[dis[i]]--] = i; for(int i = cnt; i >= 1; i--) { int p = id[i]; sz[fa[p]] += sz[p]; } } void solve(int *s, int n) { memset(mx, 0, sizeof(int)*(cnt+1)); memset(mn, inf, sizeof(int)*(cnt+1)); for(int i = 1, p = 1; i <= n; i++) { p = ch[p][s[i]]; mx[p] = mn[p] = i; } for(int i = cnt; i >= 1; i--) { int p = id[i]; mx[fa[p]] = max(mx[fa[p]], mx[p]); mn[fa[p]] = min(mn[fa[p]], mn[p]); } int ans = 0; for(int i = 2; i <= cnt; i++) { ans = max(ans, min(mx[i]-mn[i], dis[i])); } if(ans < 4) puts("0"); else printf("%d\n", ans+1); } } sam; int main() { while(scanf("%d", &n) != EOF && n) { sam.init(); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i < n; i++) s[i] = a[i+1]-a[i]+base; for(int i = 1; i < n; i++) sam.extend(s[i], i); sam.getSize(n-1); sam.solve(s, n-1); } return 0; } /* */