#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int p[2000010];//记录以s[i]为中心的回文串最大可向右延伸几位,p[i]-1为原串以i为中心的最长回文串长度
int Find(string s)
{
int mx=0,id=0;//mx记录向右延伸到的最大值,id记录最长回文串的中心下标
memset(p,0,sizeof(p));
int l=s.size();
for(int i=1; i<l; i++)
{
if(mx>i)
p[i]=min(p[2*id-i],mx-i);//j=2*id-i ; id为i与j的对称点,当mx-i>p[j],i会延伸到和j一样,反之会延伸到和mx-i一样
else
p[i]=1;
while(s[i-p[i]]==s[i+p[i]])//一个一个往后匹配相同长度加1
p[i]++;
if(i+p[i]>mx)//更新mx和id
{
mx=i+p[i];
id=i;
}
}
for(int i=0; i<l; i++)
if(i+p[i]==l)//找到可延伸到原串最后的最长回文串,返回长度
return p[i]-1;
}
int main()
{
int ncase,Z=0;
scanf("%d",&ncase);
while(ncase--)
{
string str,x;
x+='$';//防止while判断越界
x+='#';
cin>>str;
int l=str.size();
for(int i=0; i<l; i++)//解决奇偶回文串,全变为奇数
{
x+=str[i];
x+='#';
}
//如果用char记得在最后加反斜杠0
printf("Case %d: %d\n",++Z,l-Find(x)+l);//差值为需要加多少达到回文串,加长度为加之后的回文串长度
}
}
Manacher算法--O(n)回文子串算法
最新推荐文章于 2024-07-15 01:47:28 发布