这个算法已经学了好几天,刚学的时候的确有点不好理解,所以今天抽个时间来写写解题报告。
给一个我们学校的OJ题目:点击打开链接
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1000011;
char str[maxn];//输入的字符串
char s[maxn<<1];//修改之后的字符串
int p[maxn<<1];//用来记录以该字符为中心的回文串的半径,
int len,ans;
void lxsb()
{
int mx=0;//用来记录回文串最右边的下标
int id=0;//当前最长回文子串的中心下标
len=(strlen(str)+1)<<1;
for(int i=0;i<len;i++)
{
s[i]='#';
p[i]=0;
}
for(int i=0;str[i]!='\0';i++)
s[(i+1)<<1]=str[i];//将字符串变成前后和字符之间都有'#'的新字符串
s[len]='\0';
ans=0;
for(int i=1;s[i]!='\0';i++)
{
if (mx > i) //防止数组p[]向两边搜索的时候越界,以此可以减少很多不必要的步骤
p[i] = min(mx - i, p[(id << 1) - 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;
}
if(p[i]-1>ans) ans=p[i]-1;
//printf("%d %d %d\n",mx,id,ans);
}
}
int main()
{
while(scanf("%s",str)!=EOF)
{
lxsb();
printf("%d\n",ans);
}
return 0;
}