BZOJ_2565_最長雙回文串_manacher
阿新 • • 發佈:2018-06-02
IV 整數 round AI 字符串 由於 abc color man
輸入長度為n的串S,求S的最長雙回文子串T,即可將T分為兩部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
BZOJ_2565_最長雙回文串_manacher
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
12
由於每個插入的‘$‘都對應原串中相鄰的兩個字符。
我們可以枚舉所有的‘$‘然後找向左延伸的最長回文l[]和向右延伸的最長回文r[]。
manacher的時候更新單個‘$‘的l[]和r[]。
然後l[]從右往左,r[]從左往右推一遍。l[i]=max(l[i],l[i+2]-2) r[i]=max(r[i],r[i-2]-2)
最後求答案即可,註意答案串的左右回文串長度大於0。
代碼:
#include <cstdio> #include <string.h> #include <algorithm> using namespace std; #define N 200050 char w[N]; int a[N],n,p[N],r[N],l[N]; int main() { scanf("%s",w+1); int i; n=strlen(w+1); for(i=1;i<=n;i++) a[i*2-1]=‘$‘,a[i*2]=w[i]; n=n<<1|1; a[n]=‘$‘; int mx=0,lst,ans=0; for(i=1;i<=n;i++) { if(i<=mx) p[i]=min(p[2*lst-i],mx-i+1); else p[i]=1; while(i-p[i]>=1&&i+p[i]<=n&&a[i-p[i]]==a[i+p[i]]) p[i]++; if(mx<i+p[i]-1) mx=i+p[i]-1,lst=i; r[i-p[i]+1]=max(r[i-p[i]+1],p[i]-1); l[i+p[i]-1]=max(l[i+p[i]-1],p[i]-1); } for(i=1;i<=n;i+=2) r[i]=max(r[i],r[i-2]-2); for(i=n;i>=1;i-=2) l[i]=max(l[i],l[i+2]-2); for(i=1;i<=n;i+=2) if(l[i]&&r[i]) ans=max(ans,l[i]+r[i]); printf("%d\n",ans); }
BZOJ_2565_最長雙回文串_manacher