标签:des style blog color strong 数据
思路:
先做一遍MANACHER,然后枚举分界点(为#)
那么以这个点为分界的最长双回文串会由最左边的能覆盖到这个点的串和最右边的能覆盖到这个点的串组成
那么扫两遍求出每个点最左和最右能覆盖到它的回文串中心。(就是反过来求以每个点为中心的回文串能覆盖哪些点
然后枚举即可
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; char s[200011]; int r[200011],lm[200011],rm[200011]; int i,n,x,z,q,len,j; char c; void Read() { while(c=getchar(),c<‘a‘||c>‘z‘); s[++n]=‘#‘; s[++n]=c; while(c=getchar(),c>=‘a‘&&c<=‘z‘){ s[++n]=‘#‘; s[++n]=c; } s[++n]=‘#‘; } void Manacher() { int i,len,l,k; len=0; for(i=1;i<=n;i++){ if(len<i){ l=0; while(s[i-l]==s[i+l]&&i-l>=1&&i+l<=n)l++; r[i]=l; } else{ l=min(len-i+1,r[k+k-i]); while(s[i+l]==s[i-l]&&i-l>=1&&i+l<=n)l++; r[i]=l; } if(i+r[i]-1>len){ len=i+r[i]-1; k=i; } } } int main() { Read(); Manacher(); r[0]=0; len=0; for(i=1;i<=n;i++){ if(i+r[i]-1>len){ for(j=len+1;j<=i+r[i]-1;j++)lm[j]=i; len=i+r[i]-1; } if(len==n)break; } len=n+1; for(i=n;i>=1;i--){ if(i-r[i]+1<len){ for(j=i-r[i]+1;j<=len-1;j++)rm[j]=i; len=i-r[i]+1; } if(len==1)break; } for(i=1;i<=n;i++)if(s[i]==‘#‘){ z=(rm[i]-i+1)*2-1+(i-lm[i]+1)*2-1-1; if(z/2>q)q=z/2; } printf("%d\n",q); }
bzoj 2565 manacher,布布扣,bubuko.com
标签:des style blog color strong 数据
原文地址:http://www.cnblogs.com/applejxt/p/3813454.html