0
点赞
收藏
分享

微信扫一扫

51Nod1088 最长回文子串/HDU3068(Manacher算法)


看到这道题我首先想到的是可以从中间向两边找相同的字符,分偶数和奇数回文串长度两种情况。不过这种方法时间复杂度很高O(n^2),应付这种水题足够了,但是对于HDU3068那道题来说需要更好的算法,即Manacher算法。

暴力算法:

#include<iostream>
#include<string>
using namespace std;
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
string s;
while(cin>>s)
{
int ans=0;
int len=s.length();
//偶数
for(int i=1;i<len;i++)
{
int Max=0;
for(int j=0;;j++)
{
if(i-j-1>=0&&i+j<len&&s[i+j]==s[i-1-j])
Max+=2;
else
break;
}
ans=max(ans,Max);
}
//奇数
for(int i=1;i<len;i++)
{
int Max=1;
for(int j=1;;j++)
{
if(i-j>=0&&i+j<len&&s[i+j]==s[i-j])
Max+=2;
else
break;
}
ans=max(ans,Max);
}
cout<<ans<<endl;
}
}

Manacher算法

#include<iostream>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<algorithm>
using namespace std;
int manacher(string s,int a[],int len)
{
a[0]=0;
int i=0,j,ans=0;
while(i<len)
{
while(i-a[i]>0&&s[i+a[i]+1]==s[i-a[i]-1])
a[i]++;
if(ans<a[i]) ans=a[i];
j=i+1;
while(j<=i+a[i]&&i-a[i]!=i+i-j-a[i+i-j])
{
a[j]=min(a[i+i-j],i+a[i]-j);
j++;
}
a[j]=max(i+a[i]-j,0);
i=j;
}
return ans;
}
int main()
{
string x;
while(cin>>x)
{
string s="#";
for(int i=0;i<x.length();i++)
{
s+=x[i];
s+="#";
}
int *p=(int *)malloc(sizeof(int)*(s.length()+1));
cout<<manacher(s,p,s.length())<<endl;
free(p);
}
}

 

举报

相关推荐

0 条评论