动态规划:
//使用flag[i][j]记录s[i--j]是否是一个回文串
//然后逐渐增加i--j的长度
//若s[i]==s[j]&&flag[i+1][j-1]则为回文串
bool flag[1010][1010];
string longestPalindrome(string s)
{
int len = s.length();
memset(flag,false,sizeof(flag));
int maxLength=1;
int index=0;
for(int i=0;i<len;i++)
{
flag[i][i]=true;
}
for(int i=0;i<len-1;i++)
{
if(s[i]==s[i+1])
{
flag[i][i+1]=true;
index=i;
maxLength=2;
}
}
for(int l=3;l<=len;l++)
{
int j=0;
for(int i=0;i<len-l+1;i++)
{
j=i+l-1;
if(s[i]==s[j]&&flag[i+1][j-1])
{
flag[i][j]=true;
maxLength=l;
index=i;
}
}
}
//cout<<maxLength<<endl;
return s.substr(index,maxLength);
}
中心扩展:
//指定下标i,之后像两边扩展,判断是否相等
void judge(int &l,int &r,string s,int len)
{
while(l>=0&&r<len&&s[l]==s[r])
{
l--,r++;
}
l++,r--;
}
string longestPalindrome(string s)
{
int len=s.length();
int maxLength=1;
int index=0;
int l,r;
for(int i=0;i<len;i++)
{
l=r=i;
judge(l,r,s,len);
if(r-l+1>maxLength)
{
maxLength=r-l+1;
index=l;
}
l=i;r=i+1;
judge(l,r,s,len);
if(r-l+1>maxLength)
{
maxLength=r-l+1;
index=l;
}
}
return s.substr(index,maxLength);
}
Manacher算法
//Manacher算法
//将串“1212321”处理成“#1#2#1#2#3#2#1#”
//求解p[i]为处理后的串下标i为中心的回文串的边界到i的长度
//有趣的是p[i]-1为对应的原串的回文串的长度
//设mx为中心下标id的串的右侧边界+1
//若i<mx,i对于中心id的对称下标为j=2*id-i
//则p[i]=min(p[j],mx-i)
//若i>=mx,则p[i]=1
//由于代码中的while循环一直从mx开始向右遍历
//故算法复杂度为o(n),看代码更有助于理解
int p[2010];
string longestPalindrome(string s)
{
int len=s.length();
if(len==0) return string("");
string str = "$#";
for(int i=0;i<len;i++)
{
str+=s[i];
str+="#";
}
//cout<<str<<endl;
len=str.length();
int id=1;
int mx=1;
p[0]=p[1]=1;
for(int i=1;i<len;i++)
{
int j=2*id-i;
if(i<mx)
{
p[i]=p[j]<=(mx-i)?p[j]:mx-i;
}else
{
p[i]=1;
}
while((i-p[i]>0)&&(i+p[i]<len)&&(str[i-p[i]]==str[i+p[i]]))
{
p[i]++;
}
if(i+p[i]>mx)
{
mx=i+p[i]-1;
id=i;
}
}
int index=0;
for(int i=1;i<len;i++)
{
if(p[i]>p[index]) index=i;
}
string retStr = "";
for(int i=index-p[index]+1;i<index+p[index];i++)
{
if(str[i]!='#') retStr+=str[i];
}
return retStr;
}