代码随想录算法训练营第五十二天 | 647.回文子串 516.最长回文子序列

647.回文子串

题目链接 文章讲解 视频讲解

动态规划法

动规五部曲:

  • dp[i][j]: 表示区间范围[i, j]的字串是否是回文串
    如果dp[i]表示下表为i的字符串有dp[i]个回文串的话,写不出递推公式,因为dp[i]和dp[i-1]没有什么关系,但如果已经知道i-j位置的字符串已经是回文串的话,只需判断i-1位置和j+1位置是否相等就可以了
  • 递推公式:
    • s[i] == s[j]:
      • 情况一:i == j, 是回文串
      • 情况二:j-i == 1, 是回文串
      • 情况三: 判断[i+1, j-1]是否是回文串,如果是,则是回文串,否则不是回文串
    • s[i] != s[j], 不是回文串
  • 初始化:军初始化为false
  • 遍历顺序:由dp[i+1][j-1]推出dp[i][j]所以遍历顺序应从下到上,从左往右
  • 打印dp数组
class Solution {
public:
    int countSubstrings(string s) {
        // dp[i][j]: 表示区间范围[i, j]的字串是否是回文串
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        int count = 0;

        // 递推公式:
        // s[i] == s[j]:
        // 情况一:i == j, 是回文串
        // 情况二:j-i == 1, 是回文串
        // 情况三: 判断[i+1, j-1]是否是回文串,如果是,则是回文串,否则不是回文串        
        // s[i] != s[j], 不是回文串

        // 初始化:均初始化为false

        // 遍历:从下到上,从左往右
        for(int i = s.size() - 1; i >= 0; --i) {
            for(int j = i; j < s.size(); ++j) {  // 求的是范围[i, j] 所以j < i没有意义
                if(s[i] == s[j]) {
                    if(j - i <= 1) {
                        dp[i][j] = true;
                        ++count;
                    } else if(dp[i+1][j-1]) {
                        dp[i][j] = true;
                        ++count;
                    }
                }
            }
        }
        return count;
    }
};

516.最长回文子序列
题目链接 文章讲解 视频讲解

动规五部曲:

  • dp[i][j]:表示以区间i-j之间最长的回文子序列长度为dp[i][j]
  • 确定递推公式:
    • s[i] == s[j]: dp[i+1][j-1] + 2
    • s[i] != s[j]: i和j不能同时家如,那么分别考虑加入i和加入j。加入i的回文子序列的最长长度为dp[i][j-1],加入j的回文子序列最长长度为dp[i+1][j], 所以dp[i][j] = max(dp[i+1][j], dp[i][j-1])
  • 初始化:if(i == j) dp[i][j] = 1;
  • 遍历顺序:从下往上,从左往右
  • 打印dp数组
class Solution {
public:
    int longestPalindromeSubseq(string s) {
        // dp[i][j]表示以区间i-j之间最长的回文子序列长度为dp[i][j]
        vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));

        // 递推公式if(s[i] == s[j]) 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]);

        // 初始化
        for(int i = 0; i < s.size(); ++i) dp[i][i] = 1;

        for(int i =  s.size() - 1; i >= 0; --i) {
            for(int j = i + 1; j < s.size(); ++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]);
            }
        }
        return dp[0][s.size() - 1];
    }
};
posted @ 2024-07-05 17:39  深蓝von  阅读(1)  评论(0编辑  收藏  举报