给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = “babad” 输出:“bab” 解释:“aba” 同样是符合题意的答案。 示例 2:
输入:s = “cbbd” 输出:“bb”
定义状态、状态转移方程
1.dp[i][j] 表示从索引 i 到索引 j 的子串是否是回文串。
2.如果s[i][j]两个字符相等,并且子串 (i+1, j-1) 也是回文串,则当前子串 (i, j) 也是回文串,即 dp[i][j] = true。
初始化
1.首先,将单个字符视为回文串,即 dp[i][i] = true。
2.检查长度为2的子串,如果两个字符相等,即 s[i] == s[i+1],则标记为回文串,即 dp[i][i+1] = true。
确定遍历方式
dp[i+1, j-1]在dp[i,j]左下角,所以应该斜着遍历。
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
vector<vector<bool>> dp(n, vector<bool>(n, false)); // 创建一个二维的dp数组,用于记录子串是否是回文串
for (int i = 0; i < n; i++) {
dp[i][i] = true; // 单个字符一定是回文串
}
for (int i = 0; i < n-1; i++) {
if (s[i] == s[i+1]) {
dp[i][i+1] = true; // 判断长度为2的子串是否是回文串
}
}
for (int length = 3; length <= n; length++) {
for (int i = 0; i < n; i++) {
int j = i + length - 1;
if (j >= n) {
break; // 防止索引越界
}
if (s[i] == s[j] && dp[i+1][j-1]) {
dp[i][j] = true; // 判断长度大于2的子串是否是回文串
}
}
}
int max_length = 0;
string result;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int length = j - i + 1;
if (dp[i][j] && length > max_length) {
max_length = j - i + 1;
result = s.substr(i, j - i + 1); // 更新最长回文子串的长度和内容
}
}
}
return result; // 返回最长回文子串
}
};