BZOJ2565: 最长双回文串(回文树)
知识点:1.前后扫描两次字符串,分别建回文树。
#include <bits/stdc++.h> using namespace std; const long long MAXN = 100002; struct PAM { char c[MAXN]; long long ch[MAXN][26]; long long fail[MAXN],len[MAXN],cnt[MAXN]; long long tot,last; long long newnode(long long lg) { len[++tot] = lg; return tot; } void init() { tot = -1; newnode(0); newnode(-1); fail[0] = 1; c[0] = '~'; last = 0; } long long getfail(long long x,long long mid) { while(c[x - len[mid] - 1] != c[x])mid = fail[mid]; return mid; } long long insert(long long t) { long long x = getfail(t,last); long long u = c[t] - 'a'; if(!ch[x][u]) { long long y = newnode(len[x] + 2); fail[y] = ch[getfail(t,fail[x])][u]; ch[x][u] = y; } cnt[last = ch[x][u]]++; return len[ch[x][u]]; } }a1,a2; long long maxn[MAXN + 2]; int main() { scanf("%s",a1.c + 1); a1.init(); a2.init(); long long l = strlen(a1.c + 1); for(long long i = 1;i <= l;i++)a2.c[l - i + 1] = a1.c[i]; for(long long i = 1;i <= l;i++) { maxn[i] = a1.insert(i); } long long ans = -1; for(long long i = 1;i <= l - 1;i++)//Wrong 1 : 一开始写成了for(int i = 1;i <= l;i++),应该是l - 1而不是l,因为最头分界点只能是第二个点。 { long long t = a2.insert(i); ans = max(ans,t + maxn[l - i]); } printf("%lld",ans); return 0; }