题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
回文的定义
正读和反读都相同的字符序列为“回文”,如“abba”、“abccba”是“回文”,“abcde”和“ababab”则不是“回文”。字符串的最长回文子串,是指一个字符串中包含的最长的回文子串。例如“1212134”的最长回文子串是“12121”。
思路
此题暴力方法时间复杂度为O(n^3),采用两个循环遍历得到所有子串,然后再用一个循环判断每个子串是否是回文子串。不过这里还是采用容易想到的动态规划方法。首先定义 dp[i][j] 为,判断 S[i,j] 区间内的字符串是不是回文子串,其中i
和j
表示子串在s
中的左右位置;接下来我们解析动态规划方法的状态转移方程,如果 S[i,j] 是回文子串,当且仅当S[i] == S[j]&&dp(i+1,j-1)==1满足, 其中 i+1<=j-1,即j-i>=2; 当然还有一种情况,j-i<2, 也就是一字母和二字母的回文,二字母的回文仅仅需要S[i] == S[j] 即可,一字母本身就是回文。以上可以列状态方程:
由此时间复杂度O(n^2),空间复杂度O(n^2)。
string getLongestPalindrome(string str, int n) { // n为字符串的长度
if (n <= 1) return str;
vector<vector<int>> dp(n, vector<int>(n, 0));
int start = 0; //回文串起始位置
int maxlen = 1; //回文串最大长度
for (int j = 0; j<n; j++){
dp[j][j] = 1; //初始化一字母回文串
for (int i = 0; i<j; i++){
//当满足(str[i] == str[j] && j-i<2) 则为初始化两字母回文串
//当满足(str[i] == str[j] && dp[i + 1][j - 1] == 1)
if (str[i] == str[j] && (j - i<2 || dp[i + 1][j - 1] == 1)){
dp[i][j] = 1;
if (maxlen < j-i+1)
{
start = i; // 更新回文串长度和位置
maxlen = j - i + 1;
}
}
}
}
return str.substr(start,maxlen);
}
参考:https://blog.youkuaiyun.com/u013309870/article/details/70742315