bzoj 2565: 最長雙回文串
阿新 • • 發佈:2017-07-14
arc 表示 print logs strlen include clu 逆序 led
輸入長度為n的串S,求S的最長雙回文子串T,即可將T分為兩部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Description
順序和逆序讀起來完全一樣的串叫做回文串。比如acbca是回文串,而abc不是(abc的順序為“abc”,逆序為“cba”,不相同)。輸入長度為n的串S,求S的最長雙回文子串T,即可將T分為兩部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小寫英文字母組成的字符串S。
Output
一行一個整數,表示最長雙回文子串的長度。Sample Input
baacaabbacabbSample Output
12HINT
樣例說明
從第二個字符開始的字符串aacaabbacabb可分為aacaa與bbacabb兩部分,且兩者都是回文串。
對於100%的數據,2≤|S|≤10^5
2015.4.25新加數據一組
Source
2012國家集訓隊Round 1 day2
正反建立回文自動機,然後可以正著可以求出以i為結尾的最長回文串,反著可以求出以i為開頭的最長回文串,
然後枚舉兩個拼起來即可;
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=200050; int nxt[N][30][2],fail[N][2],len[N][2],le,last,tt[2],ans[N][2]; char s[2][N]; void insert(int n,int c,int flag){ int cur=last; while(s[flag][n-len[cur][flag]-1]!=s[flag][n]) cur=fail[cur][flag]; if(!nxt[cur][c][flag]){ int now=++tt[flag],la=fail[cur][flag]; len[now][flag]=len[cur][flag]+2; while(s[flag][n-len[la][flag]-1]!=s[flag][n]) la=fail[la][flag]; fail[now][flag]=nxt[la][c][flag],nxt[cur][c][flag]=now; } last=nxt[cur][c][flag];ans[n][flag]=len[last][flag]; } int main(){ scanf("%s",s[0]+1);le=strlen(s[0]+1); for(int i=1;i<=le;i++) s[1][le-i+1]=s[0][i]; len[++tt[0]][0]=-1,len[++tt[1]][1]=-1; fail[0][0]=1;fail[0][1]=1; for(int i=1;i<=le;i++) insert(i,s[0][i]-‘a‘+1,0); for(int i=1;i<=le;i++) insert(i,s[1][i]-‘a‘+1,1); int Ans=0; for(int i=1;i<le;i++) Ans=max(Ans,ans[i][0]+ans[le-i][1]); printf("%d\n",Ans); }
bzoj 2565: 最長雙回文串