算法问题描述
求回文子串
算法思想
字符串的思想一般都是用前面求过的加速后面的,马拉车算法也不例外,先强行搞一个东西,在每个字符中间插入一个不会出现的字符‘#‘’’以处理奇回文和偶回文(代码方便)
如果现在有一个大的以id为对称轴的回文串,现在要更新id右边的某个i的最大回文半径,如果i在id回文串内,是不是可以直接用i的关于id的对称点的回文半径呢?
所以我们分情况讨论一下。记i的关于id的对称点为j,回文半径为p[i]-1(代码方便)
1.j的回文串超过id的回文串,那么i的回文串半径就等于j在i里面的回文半径,因为!!!如果i的回文串也超过id的回文串,那么id的回文串应该更长一点
2.j的回文串在id的回文串里面,那么显然barabara,p[i]=p[j]
3.j的回文串刚好贴着id的回文串,那么p[i]=p[j],并且!!!!,p[i]有增长的空间,要p[i]++去试
答案要去掉’#’,所以通过计算(听别人说),刚刚好就是p[i]-1
代码
int n,m,p[maxn];
char _ch[maxn],ch[maxn]={};
int init(){
int cnt=0;
scanf("%s",_ch+1);
int len=strlen(_ch+1);
ch[++cnt]='$';
for(int i=1;i<=len;i++){
ch[++cnt]='#';
ch[++cnt]=_ch[i];
}
ch[++cnt]='#';
ch[++cnt]='\0';
}
void Manacher(){
int len=strlen(ch+1),id,mx=0;
for(int i=2;i<=len;i++){
if(i<mx) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(ch[i-p[i]]==ch[i+p[i]]) p[i]++;
if(mx<i+p[i]) mx=i+p[i],id=i;
}
}