题目描述
给定一个字符串,求它的最长回文子串的长度。
解法一
枚举中心位置,然后再在该位置上用扩展法,记录并更新得到的最长的回文长度
#include<iostream>
#include<cstring>
using namespace std;
int longestPalindrome(char *s,int n)
{
if(s==NULL||n<1)
{
return 0;
}else if(n==1)
{
return 1;
}
char* first=s;
char* last=s+n-1;
char* str1;
char* str2;
int max=1;
int len;
if(n%2!=1)//长度n为偶数:maddam
{
while(first<last)
{
len=0;
str1=first;
str2=first+1;
while(str1>=s)
{
if(*(str1--)==*(str2++))
{
len=len+2;
}
else
{
break;
}
}
max=max>len?max:len;
first++;
}
}
else //长度n为奇数:madam
{
while(first<last)
{
len=1;
str1=first-1;
str2=first+1;
while(str1>=s)
{
if(*(str1--)==*(str2++))
{
len=len+2;
}
else
{
break;
}
}
max=max>len?max:len;
first++;
}
}
return max;
}
int main()
{
char*str1="cdmadamegfh";
char*str2="fsdgmaddamgf";
cout<<longestPalindrome(str1,11)<<endl;//5
cout<<longestPalindrome(str2,12)<<endl;//8
return 0;
}
解法二、O(N)解法
在上文的解法一:枚举中心位置中,我们需要特别考虑字符串的长度是奇数还是偶数,所以导致我们在编写代码实现的时候要把奇数和偶数的情况分开编写,是否有一种方法,可以不用管长度是奇数还是偶数,而统一处理呢?比如是否能把所有的情况全部转换为奇数处理?
答案还是肯定的。这就是下面我们将要看到的Manacher算法:
#include<iostream>
#include<cstring>
using namespace std;
void stringTransform(char cstr1[],char cstr2[])
{
int ix2=0;
cstr2[ix2++] ='#';
for(int ix1=0;cstr1[ix1]!='\0';++ix1)
{
cstr2[ix2++]=cstr1[ix1];
cstr2[ix2++]='#';
}
cstr2[ix2]='\0';
}
void longestPalindrome(char cstr2[],int p[])
{
int right=0;//当i=0时,right=0,center=0,所以下面循环无需再判断i=0时的情况
int center=0;
for(int i=1;cstr2[i]!='\0';i++)
{
if(right-i>0)
p[i]=p[2*center-i]>(right-i)?(right-i):p[2*center-i];//p[i]=min{p[2*center-i],(right-i)}
while(cstr2[i+p[i]+1]!='\0'&&(i-p[i]-1>=0)&&cstr2[i+p[i]+1]==cstr2[i-p[i]-1])
p[i]++;
if(i+p[i]>right)
{
center=i;
right=i+p[i];
}
}
}
int main()
{
char *cstr1="babcbabcbaccba";
char cstr2[25];
int p[50];
for(int i=0;i<50;i++)
{
p[i]=0;
}
stringTransform(cstr1,cstr2);
cout<<cstr2<<endl;
longestPalindrome(cstr2,p);
for(int j=0;j<strlen(cstr2);j++)
{
cout<<p[j];
}
cout<<endl;
return 0;
}
http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html