(算法)最长回文子串
题目:
求一个字符串的最长回文子串
思路:
1、暴力枚举
最容易想到的就是暴力破解,列举每一个子串,然后根据回文的定义判断是不是回文,找到最长的那个。
求每一个子串的时间复杂度为O(N^2),判断子串是不是回文的时间复杂度为O(N),所以时间复杂度为O(N^3)。
2、动态规划
回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1,j-1]也是回文字符串。这样最长回文子串就能分解成一系列子问题了。
这样需要额外的空间是O(N^2),时间复杂度也是O(N^2)。
状态转移方程:
当str[i]=str[j] dp[i][j]=dp[i+1][j-1]
当str[i]!=str[j] dp[i][j]=0
初始状态:
dp[i][i]=1
dp[i][i+1]=1 if str[i]=str[i+1]
3、中心扩展
中心扩展就是把给定的字符串的每一个字符当做中心,向两边扩展,这样来找最长的子回文串。时间复杂度为O(N^2)。
但是要考虑两种情况:
如aba,这样长度为奇数。
如abba,这样长度为偶数。
4、Manacher法
待续
代码:
#include<iostream>
using namespace std;
// brute force
string findLongestPalindrome_1(string &str){
int length=str.size();
int maxLength=0;
int start;
for(int i=0;i<length;i++){
for(int j=i+1;j<length;j++){
int left,right;
for(left=i,right=j;left<right;left++,right--){
if(str[left]!=str[right])
break;
}
if(left>=right && (j-i)>maxLength){
maxLength=j-i+1;
start=i;
}
}
}
if(maxLength>0)
return str.substr(start,maxLength);
return NULL;
}
// dynamic programming
string findLongestPalindrome_2(string &str){
const int length=str.size();
int maxLength=1;
int start;
bool dp[length][length];
for(int i=0;i<length;i++)
for(int j=0;j<length;j++)
dp[i][j]=false;
for(int i=0;i<length;i++){
dp[i][i]=true;
if(i<length-1 && str[i]==str[i+1]){
dp[i][i+1]=true;
start=i;
maxLength=2;
}
}
for(int len=3;len<=length;len++){
for(int i=0;i<=length-len;i++){
int j=i+len-1;
if(dp[i+1][j-1] && str[i]==str[j]){
dp[i][j]=true;
start=i;
maxLength=len;
}
}
}
if(maxLength>=2)
return str.substr(start,maxLength);
return NULL;
}
// pivot expand
string findLongestPalindrome_3(string &str){
const int length=str.size();
int maxLength=1;
int start;
for(int i=0;i<length;i++){
int left=i-1;
int right=i+1;
while(left>=0 && right<=length-1 && str[left]==str[right]){
if(right-left+1>maxLength){
start=left;
maxLength=right-left+1;
}
left--;
right++;
}
}
for(int i=0;i<length;i++){
int left=i;
int right=i+1;
while(left>=0 && right<=length-1 && str[left]==str[right]){
if(right-left+1>maxLength){
start=left;
maxLength=right-left+1;
}
left--;
right++;
}
}
if(maxLength>0)
return str.substr(start,maxLength);
return NULL;
}
int main(){
string str="ababcddcbbd";
cout<<findLongestPalindrome_1(str)<<endl;
cout<<findLongestPalindrome_2(str)<<endl;
cout<<findLongestPalindrome_3(str)<<endl;
return 0;
}

浙公网安备 33010602011771号