5. 最长回文子串

给你一个字符串 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;  // 返回最长回文子串
    }
};

你可能感兴趣的:(算法,动态规划)