A - 最长回文(马拉车算法//manacher)
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
回文就是正反读都是一样的字符串,如aba, abba等
Input输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000Output每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input
aaaa abab
Sample Output
4 3
https://www.cnblogs.com/csx-zzh/p/13445701.html
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define Max 110005 using namespace std; char ma[Max*2]; int mp[Max*2]; void manacher(char s[],int len) { int l=0; ma[l++]='$'; ma[l++]='#'; for(int i=0;i<len;i++) { ma[l++]=s[i]; ma[l++]='#'; } /* a b a b c */ /*$ # a # b # a # b # c # */ ma[l]='\0'; int mx,id;//mx为以id为中心的最长回文串的右界 id+p[id]=mx [id-p[id]~mx] //若遍历到i,有i<mx :if(i<mx) p[i]=min(p[j=2*id-i],mx-i) for(int i=0;i<l;i++) { mp[i]=mx>=i?min(mp[2*id-i],mx-i):1; while(ma[i+mp[i]]==ma[i-mp[i]]) // 不需边界判断,因为左有'$',右有'\0' mp[i]++;//j 回文串左端正好与 id 的回文串左端重合时 // 我们每走一步 i,都要和 mx 比较,我们希望 mx 尽可能的远,这样才能更有机会执行 if (i < mx)这句代码,从而提高效率 if(i+mp[i]>mx)//更新 id,mx; { mx=i+mp[i]; id=i; } } } int main() { while(~scanf("%s",s)) { int len=strlen(s); int ans=0; manacher(s,len); for(int i=0;i<2*len+2;i++) ans=max(ans,mp[i]-1);//性质:最长回文长度=mp[i]-1; mp[i]个'#',mp[i]-1个字符,原长2*mp[i]-1; printf("%d\n",ans); } }