动态规划典中典之最长回文子串

80 阅读1分钟

给定一个字符串 s,找到 s 中最长的回文子串。

  1. 确定是最值问题,解题过程可枚举,考虑动态规划解法。
  2. 最坏情况初值:字符串所有字符都不同,回文子串长度最长也只有1;
  3. 最后一步:假定s[0,i-1]的最长回文子串为s[m,n],0 <= m <=n <= i-1;s[m,n]向左右各扩充1个字符,如果这两个字符相等,则回文字符串可扩展2
  4. 最后一步2:更好的方式,以长度作为枚举
class Solution {
public:
    string longestPalindrome(string s) {
        // 边缘场景
        if(s.empty()) {
            return 0;
        }
        int n = s.size();
        int start = 0, maxLen = 1;
        // 定义状态:isPalindrome[i][j] 表示 s[i]~s[j]是否为回文串
        vector<vector<int>> isPalindrome(n, vector<int>(n, false));
        // 单个字符和两个字符作为 DP边界
        for(int i = 0; i < n-1; i++) {
            isPalindrome[i][i] = true;
            isPalindrome[i][i+1] = s[i] == s[i+1];
            if(isPalindrome[i][i+1]) {
                maxLen = 2;
                start = i;
            }
        }
        isPalindrome[n-1][n-1] = true;
        for(int len = 3; len <= n; len++) {
            for(int i = 0; i < n-len+1; i++) {
                // DP转移:某字符串为回文串的充要条件为前后去掉一个字符的子串为回文串,且前后字符相等
                isPalindrome[i][i+len-1] = isPalindrome[i+1][i+len-2] && s[i] == s[i+len-1];
                if(isPalindrome[i][i+len-1]) {
                    start = i;
                    maxLen = len;
                }
            }
        }
        return s.substr(start, maxLen);
    }
};