题目:
求一个字符串的最长回文子串
思路:
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; }