最长回文子串与最长回文子序列

最长回文子串

  • 定义状态
    \(dp[i][j]\) 表示子串 \(s[i..j]\) 是否为回文子串,这里子串 \(s[i..j]\) 定义为左闭右闭区间,可以取到 \(s[i]\)\(s[j]\)

  • 状态转移方程
    \(dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]\)

  • 编码技巧
    本体是典型的二维dp.因为子串是连续的,短的子串会为通过递进的方式,从而可以判断长的子串。因此本体的遍历方式第一层for 循环控制遍历子串的长度,第二层for循环为子串的左边界,当然右边界根据左边界以及子串的长度可以很轻松得到

class Solution {
public:
    string longestPalindrome(string s) {
        string ans = "";    
        int n = s.size(); 
        vector<vector<bool>> dp(n , vector<bool> (n, false));
        for(int l = 0; l < n; l++){
            for(int i = 0; i + l < n; i++){
                int j = i + l;
                if (l == 0)
                    dp[i][j] = true;
                else if (l == 1)
                    dp[i][j] = s[i] == s[j];
                else 
                    dp[i][j] = ( (s[i] == s[j]) && dp[i+1][j-1] );
                
                if (dp[i][j] && l + 1 > ans.size())
                    ans = s.substr(i, l+1);
            }
        }
        return ans;
    }
};

最长回文子序列

这里我们一定要注意到,最长回文子序列与最长子串的区别,子序列相对子串可以是不连续的,也就是自序列是原本字符串中提取的一系列字符串,另外子序列不能改变原来子串的长度!!

  • 递推公式
    \(dp[i][j] = dp[i+1][j-1] + 2; s[i] == s[j]\)
    \(dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); s[i] != s[j]\)
  • 编码技巧
    这里因为子序列是不连续的,所以我们没法再像上面的解法,先使用一个for 循环 一下长度, 我们在这里直接遍历两个指针的所有情况!但是注意啊,根据动态规划方程我们可以得知 \([i,j]\) 是由\([i+1, j-1]\)递推而来的,也就是所\(i+1 -> i\), \(j-1->j\),所以\(i\)应该反着遍历,而\(j\)应该正着遍历。
class Solution {
public:
int longestPalindromeSubseq(string s) {
    int n = s.size();
    // dp 数组全部初始化为 0
    vector<vector<int>> dp(n, vector<int>(n, 0));
    // base case
    for (int i = 0; i < n; i++)
        dp[i][i] = 1;
    // 反着遍历保证正确的状态转移
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i + 1; j < n; j++) {
            // 状态转移方程
            if (s[i] == s[j])
                dp[i][j] = dp[i + 1][j - 1] + 2;
            else
                dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
        }
    }
    // 整个 s 的最长回文子串长度
    return dp[0][n - 1];
}
};
          
posted @ 2020-10-31 17:04  wsl-hitsz  阅读(147)  评论(0编辑  收藏  举报