题目描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
解决方案:
采用动态规划法:
回文字符串的子串也是回文,比如p[i,j](表示以i开始以j结束的子串)是回文字符串,那么p[i+1,j-1]也是回文字符串。这样最长回文子串就能分解成一系列子问题了。
由于最长回文子串是要求连续的,所以我们可以假设i为子串的起始坐标,j 为子串的终点坐标,其中 i 和 j 都是大于等于 0 并且小于字符串长度 len 的,且 i<= j,这样子串的长度就可以使用 j - i + 1 表示了。
我们从长度为 1 的子串依次遍历,长度为 1 的子串肯定是回文的,其长度就是 1;然后是长度为 2 的子串依次遍历,只要 s[i] 等于 s[i+1] ,它就是回文的,其长度为 2;接下来就好办了,长度大于 2 的子串,如果它要满足是回文子串的性质,就必须有 s[i] 等于 s[j] ,并且去掉两头的子串 s[i+1 … j-1] 也一定是回文子串,由于我们是从子问题依次增大求解的,所以求解 [i … j] 的问题时,比它规模更小的问题结果都是可以直接使用的了
C++代码如下:
class Solution {
public:
string longestPalindrome(string s) {
int len = s.size();
int maxlen = 0;
int start;
bool p[1000][1000] = {false};
for (int i = 0; i<len;i++){
p[i][i] = true;
if (i<len && s[i] == s[i+1]){
p[i][i+1] = true;
maxlen = 2;
start = i;
}
}
for (int l = 3; l<len; l++){
for (int i = 0; i < len-l; i++){
int j = l+i-1;
if (p[i+1][j-1] && s[i] == s[j]){
p[i][j] = true;
maxlen = l;
start = i;
}
}
}
if (maxlen > 2)
return s.substr(start,maxlen);
return NULL ;
}
};