这个算法用于寻找一个字符串中的最长回文串的长度,利用对称减少遍历次数
思路:
这里前半部分讲的不错
总体思路讲的很好
其实与暴力解决紧密联系,利用上一次的回文串以及对称性,省去了很多暴力次数,但最后仍然需要暴力,每一次能够帮助到我们减少次数的上限是mx-i
声明:id是在i之前的最长回文串的中心,mx则是对应的右端点,i是当前遍历到的点,j是i关于id的对称点,out[i]是i这个点的最长回文串长度
情况一:i<mx,这时候就能帮助到我们减少次数,这里能帮助到的上限是mx-i,即能辅助检测到的回文串最长是mx-i,一旦超出要进入暴力模式,如果说out[j]<mx-i,那就能够取得到,out[i]恰好等于out[j]
情况二:i>=mx,爱莫能助,我们只能按部就班暴力
#include<algorithm>
#include<stdio.h>
#include<cstring>
using namespace std;
char a[51000005],mod[51000005];
int out[51000005];
int modify()//这个函数将不同符号插入到原字符串中
{ //实现无论奇数还是偶数字符串都会变成奇数
int len=strlen(a);
int j=2,i;
mod[0]='^';//防止越界,没东西匹配
mod[1]='#';
for(i=0;i<=len-1;i++)
{
mod[j++]=a[i];//mod[j]被赋值后j才加1
mod[j++]='#';
}
return j;
}
int manacher()
{
int i;
int len=modify();
int mid=1,maxright=1,ans=-1;//maxright是当前回文串的最右边
for(i=1;i<=len-1;i++)//mid是对称中心
{
if(i<maxright) out[i]=min(maxright-i,out[2*mid-i]);
else out[i]=1;
while(mod[i-out[i]]==mod[i+out[i]])//暴力
{
out[i]++;
}
if(i+out[i]>maxright)///
{ 这里都是在更新
maxright=i+out[i]; 新的最右端和对称中心
mid=i; 以及最长回文串长度
}
ans=max(ans,out[i]-1);
}
return ans;
}
int main()
{
scanf("%s",a);
printf("%d",manacher());
return 0;
}