字符串最大回文子串(Manacher 算法)
以HDU-3068为例
题目:
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正反读都是一样的字符串,如aba, abba等
Input:
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S两组case之间由空行隔开(该空行不用处理)字符串长度len <= 110000
Output:
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input
aaaa
abab
Sample Output
4
3
#include<cstdio>
#include<cstring>
#include <algorithm>
#include<cmath>
using namespace std;
const int maxn = 1e5+1e4+10;
char c[maxn];//原字符串
char s[maxn*2];//转换后的字符串
int p[maxn*2];//P可以理解为回文字符串的半径
void init(){
int l=strlen(c);
int i;
for(i=0; i<l; ++i){
s[i*2+1]='#';
s[i*2+2]=c[i];
}
s[0]='@';//字符串开头增加一个特殊字符,防止越界
s[i*2+1]='#';
s[i*2+2]='0';//字符串结尾加一个字符,防止越界
}
int Manacher(){
int mx=0,id=0;//mx即为当前计算回文串最右边字符的最大值
int i;
for(i=1; s[i]!='0'; ++i){
if(mx>i)
p[i]=min(p[2*id-i],mx-i);
else
p[i]=1;
while(s[i+p[i]] == s[i-p[i]])
p[i]++;
if(i+p[i]>mx){
mx=i+p[i];
id=i;
}
}
mx=0;
for(int i=0; s[i]!='0'; ++i){
if(p[i]>mx)
mx=p[i];
}
return mx-1;//返回p[i]中的最大值-1即为原串的最长回文子串额长度
}
int main(){
while(~scanf("%s",c)){
init();
printf("%d\n",Manacher());
}
return 0;
}
O(n)算法
在每个字符中间插入'#'号,使原来偶数长的回文串的中心轴可以用'#' 表示出来。
三个链接以供参考
https://blog.csdn.net/synapse7/article/details/18908413