1. 程式人生 > >[BZOJ2565]最長雙回文串

[BZOJ2565]最長雙回文串

source void span AC 回文子串 esp pri Go algorithm

bzoj

題意

輸入長度為\(n\)的串\(S\),求\(S\)的最長雙回文子串\(T\),即可將\(T\)分為兩部分\(X,Y\)\((|X|,|Y|≥1)\)\(X\)\(Y\)都是回文串。

sol

顯然是枚舉\(X\)\(Y\)在那個地方斷吧。
那麽就需要求出位置\(i\)的最長回文後綴和\(i+1\)的最長回文前綴,然後拼起來就可以了。
回文後綴可以直接回文樹求。
回文前綴?
\(reverse\)過來再做一遍即可。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using
namespace std; const int N = 1e5+5; struct Palindromic_Tree{ int last,tot,tr[N][26],fa[N],len[N]; void init(){fa[0]=fa[1]=1;len[tot=1]=-1;} void extend(int c,int n,char *s) { int v=last; while (s[n-len[v]-1]!=s[n]) v=fa[v]; if (!tr[v][c]) { int
u=++tot,k=fa[v]; len[u]=len[v]+2; while (s[n-len[k]-1]!=s[n]) k=fa[k]; fa[u]=tr[k][c];tr[v][c]=u; } last=tr[v][c]; } }t1,t2; char s[N];int f[N],g[N]; int main() { scanf("%s",s+1); int n=strlen(s+1),ans=0
; t1.init();t2.init(); for (int i=1;i<=n;++i) t1.extend(s[i]-'a',i,s),f[i]=t1.len[t1.last]; reverse(s+1,s+n+1); for (int i=1;i<=n;++i) t2.extend(s[i]-'a',i,s),g[n-i+1]=t2.len[t2.last]; for (int i=1;i<n;++i) ans=max(ans,f[i]+g[i+1]); printf("%d\n",ans);return 0; }

[BZOJ2565]最長雙回文串