方法:求字符串的
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e6+9;
char s[N];
int p[N];
int main()
{
cin>>s+1;
int n=strlen(s+1);
s[0]='^';s[2*n+2]='$';
for(int i=2*n+1;i>=1;i--)
{
s[i]=(i&1)?'#':s[i>>1];//右移表示除2
}
int C=0,R=0;
//C表示最长回文串的中心
//R表示最长回文串的回文半径
for(int i=1;i<=2*n+1;i++)
{
//半径初始化
p[i]=(i<R)?min(p[2*C-i],C-i):1;
//暴力搜索
while(s[i+p[i]]==s[i-p[i]])p[i]++;
if(i+p[i]>R)C=i,R=i+p[i];
}
int ans=0;
for(int i=1;i<=2*n+1;i++) ans=max(ans,p[i]-1);
cout<<ans<<endl;
return 0;
}
转换之后的回文半径和转换之前的回文串长度的关系
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e6+9;
char s[N];
int p[N];
int main()
{
cin>>s+1;
int n=strlen(s+1);
s[0]='^';s[2*n+2]='$';//设置开头和结尾的哨兵
for(int i=2*n+1;i>=1;i--)
{
s[i]=(i&1)?'#':s[i>>1];//在原字符串中插入'#'号
}
int C=0,R=0;//C表示最长回文子串的中心位置,R表示当前
for(int i=1;i<=2*n+1;i++)
{
p[i]=i<R?min(R-i,p[2*C-i]):1;//判断i是否在盒子里
//在的话就取对称半径和当前点到边界的最小值
//不在的话就将半径设置为1
while(s[i+p[i]]==s[i-p[i]])p[i]++;
//然后开始暴力搜索,结果是当前点的最大回文半径
if(i+p[i]>R) C=i,R=i+p[i];
//如果当前点的最大回文半径是最大的则更新为最大回文半径,
// 当前点更新为新的中心
}
int ans=0;
for(int i=1;i<=2*n+1;i++)
{
ans=max(ans,p[i]-1);
}
// 转换之后最长回文半径-1 = 转换之前最长回文子串的长度。
cout<<ans<<endl;
return 0;
}
最长回文子串