bzoj 2342: [Shoi2011]双倍回文 -- manacher
2342: [Shoi2011]双倍回文
Time Limit: 10 Sec Memory Limit: 128 MBDescription
Input
输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。
Output
输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。
Sample Input
16
ggabaabaabaaball
ggabaabaabaaball
Sample Output
12
HINT
N<=500000
Source
首先我们manacher处理出每个位置的最长回文串
然后我们枚举对称轴,根据题意可以知道对称轴一定在两个字符中间(即"#"处)
并对于每边分别枚举对称轴,判断是否合法
#include<map> #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long #define N 1000100 int n,mx,md,p[N],ans; char c[N],s[N]; int main() { scanf("%d%s",&n,s+1);c[0]='*'; for(int i=1;i<=n;i++){c[(i<<1)-1]='#';c[i<<1]=s[i];} n<<=1;c[++n]='#';c[++n]='!'; for(int i=1;i<n;i++) { p[i]=mx>i?min(p[(md<<1)-i],mx-i):1; while(c[i-p[i]]==c[i+p[i]]) p[i]++; if(p[i]+i>mx) mx=p[i]+i,md=i; } for(int i=1;i<n;i+=2) { int j=p[i]>>1;if(j&1) j--; for(;j&&j*2>ans;j-=2) if(p[i-j]>j&&p[i+j]>j) ans=max(ans,j<<1); } printf("%d\n",ans); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。