朴素方法:虽然这种方法做了优化,但时间复杂度超过O(N^2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
#define N 110002
char s[N];
int judge(int i,int j)
{
int len=j-i+1;
for(int k=0;k<len/2;k++)
if(s[i+k]!=s[j-k])
return 0;
return len;
}
int main()
{
int i,j;
while(~scanf("%s",s))
{
if(s[0]=='\0')
continue;
int len=strlen(s);
int MAX=1;
for(i=0;len-i>MAX;i++)
for(j=len-1;j-i+1>MAX;j--)
{
int temp=judge(i,j);
if(temp>MAX)
MAX=temp;
}
printf("%d\n",MAX);
}
return 0;
}
下面介绍一个时间复杂度为O(n)的算法:manacher 算法
主要利用回文字符串的对称性;有一定的技巧性,自己仔细看代码
可以AC HDU 3068 最长回文
耗时: 281MS 时间限制:2s
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define INF 1<<30
#define M 110005
#define kind 26
char str[M],ch[M<<1];
int dp[M<<1];//记录修改后串的单边长度
int solve()
{
int i,n;//n记录长度
int ans=1;
//处理加工成$#a#b#c#0//总个数为奇数个[0,i<<1]
for(i=1;str[i]!='\0';i++)//这里注意别把"\0" 写成"0"
{
ch[i<<1]=str[i];
ch[(i<<1)+1]='#';
}
ch[0]='$';ch[1]='#';
n=(i<<1);
ch[n]=0;
int maxID=0,id=0;
for(i=1;i<n;i++)
{
if(maxID>i)
dp[i]=min(dp[id*2-i],maxID-i);
else
dp[i]=1;
while(ch[i-dp[i]]==ch[i+dp[i]])
dp[i]++;
if(dp[i]+i>maxID)
{
maxID=dp[i]+i;
id=i;
}
if(dp[i]>ans)
ans=dp[i];
}
return ans-1;
}
int main()
{
while(~scanf("%s",&str[1]))
{
printf("%d\n",solve());
}
return 0;
}