马拉车
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int M=1000010; int p[M]; ///记录以i为中心的最大回文半径 char a[M]; ///原始字符串 char b[M]; ///优化字符串 void manacher() { ///第一阶段:字符串优化 int i,k,l; l=strlen(a); ///原始字符串长度 b[0]='$'; ///防止出界 b[1]='#'; ///加入输入字符串未出现的字符 ///目的:使偶数字符串变为奇数字符串 k=2; ///优化字符长度记录 for(i=0;i<l;i++) { b[k++]=a[i]; b[k++]='#'; } b[k]=0; ///目的:设置边界 ///第二阶段:寻找最大回文串的长度 int id=0,mx=0; ///mx为以id为中心的最右边的边界:mx=id+p[id]; int len=0; ///记录最大回文串长度 for(i=1;i<k;i++) { if(i<mx) ///判断:如果i在id的右边界内 { p[i]=min(p[2*id-i],mx-i); ///核心:2*id-i是i关于id的对称点,设为j,如果对称点p[j]<=mx-i,说明未出界,p[i]=p[j]; /// 如果对称点p[j]>mx-i,说明出界,界外的字符未知,需要一个一个判断,此时p[i]!=p[j]; } else p[i]=1; ///如果i出id的右边界,则初始回文半径为1 while(b[i+p[i]]==b[i-p[i]]) ///不需要判断边界,因为左有$,右有0 p[i]++; ///判断界外关于i对称字符是否相等,相等回文半径长度增加 if(p[i]>mx-i) ///判断i的右边界和id右边界的大小 { mx=i+p[i]; ///i的右边界大,更新边界mx和中心点id id=i; } if(p[i]-1>len) ///p[i]-1为回文串的长度 len=p[i]-1; ///更新最大长度 } printf("%d\n",len); } int main() { while(~scanf("%s",a)) manacher(); return 0; }