题目如下:
解题思路:
首先弄清楚什么是回文字符串,即正反读都相同的字符串,例如 “上海在海上”、“abfgfba” 等。
1、方法一当然是最简单的暴力求解:
将以每个字符为首的子串都遍历一遍,判断是否为回文;如果是回文,再判断最大长度的回文子串。算法简单,但是算法复杂度高:O(n^3)。
代码如下:
class Solution {
public:
string longestPalindrome(string s){
if(s.empty()) return "";
if(s.size()==1) return s;
int start=0, maxlength=1;//记录最大回文子串的起始位置以及长度
for(int i=0; i<s.size(); i++){
for(int j=i+1; j<s.size(); j++){//从当前位置的下一个开始算
int temp1, temp2;
for(temp1=i,temp2=j; temp1<temp2; temp1++,temp2--){
if(s[temp1] != s[temp2])
break;
}
//这里要注意条件为temp1>=temp2,因为如果是偶数个字符,相邻的两个经上一步会出现大于的情况
if(temp1 >= temp2 && j-i+1 > maxlength){
maxlength = j-i+1;
start=i;
}
}
}
//利用string中的substr函数来返回相应的子串,第一个参数是起始位置,第二个参数是字符个数
return s.substr(start,maxlength);
}
};
2、方法二则是采用动态规划DP来求解:
对于字符串str,假设dp[i,j]=1表示str[i...j]是回文子串,那个必定存在dp[i+1,j-1]=1。这样最长回文子串就能分解成一系列子问题,利用动态规划来求解。首先构造状态转移方程:
- dp[i, j] = dp[i+1, j-1],str[i] = str [j]
- dp[i, j] = 0 , str[i] != str[j]
上面的状态转移方程表示,当str[i]=str[j]时,如果str[i+1...j-1]是回文串,则str[i...j]也是回文串;如果str[i+1...j-1]不是回文串,则str[i...j]不是回文串。注意单个字符,两个相同字符都是回文串。
- dp[i][i]=1
- dp[i][i+1]=1 if str[i]==str[i+1]
class Solution {
public:
string longestPalindrome(string s) {
int len = s.size();
int start = 0;
int maxlength = 1;
//dp[i,j]用于记录子问题结果,为1表示s[i] == s[j]
vector<vector<int> > dp(len, vector<int>(len));
if(len == 0)
return "";
else if(len == 1)
return s;
//初始化所有的dp[i][i]、满足条件的dp[i][i+1]都是回文串(即“a”、“aa”)
for(int i = 0; i < len; i++){
dp[i][i] = 1;
if(i < len - 1 && s[i] == s[i+1]){
dp[i][i+1] = 1;
start = i;
maxlength = 2;
}
}
for(int l = 3; l <= len; l++){ //子串长度
for(int i = 0; i+l-1 < len; i++)
{
int j = i + l - 1; //终点
if(s[i] == s[j] && dp[i+1][j-1] == 1){
dp[i][j] = 1;
start = i;
maxlength = l;
}
}
}
return s.substr(start, maxlength);
}
};
需要用一个二维数组dp来作为记录子问题的结果,这也是动态规划的精髓所在。动态规划方法的算法复杂度是O(n^2)。