代码随想录训练营第五十七天

1.回文子串 题647

①dp数组含义

判断回文子串可以用头元素和尾元素是否相等的方式,设dp[i] [j]为[i,j]子串是否为回文子串,是则为true,否为false。

②递推公式

若 s[i] == s[j] ,分三种情况:i == j,即只有一个元素,那么只有一个回文子串,结果为true;

​ j - i =1,比如aa,那么也是回文子串,结果为true;

​ j - i >=1, 就得看dp[i+1] [j-1]的结果,结果与dp[i+1] [j-1]相同。

代码随想录训练营第五十七天_第1张图片

③初始化

全部默认为false。

④遍历顺序

看递推方向,从下往上,从左到右。

代码随想录训练营第五十七天_第2张图片

class Solution {
public:
    int countSubstrings(string s) {
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        int result = 0;
        for (int i = s.size() - 1; i >= 0; i--) {  // 注意遍历顺序
            for (int j = i; j < s.size(); j++) {      //j必须大于等于i
                if (s[i] == s[j]) {
                    if (j - i <= 1) { // 情况一 和 情况二
                        result++;
                        dp[i][j] = true;
                    } else if (dp[i + 1][j - 1]) { // 情况三
                        result++;
                        dp[i][j] = true;
                    }
                }
            }
        }
        return result;
    }
};

2.最长回文子序列 题516

首先是子序列,然后才是回文,而子序列不一定是连续的。

①dp数组含义

跟回文子串差不多。[i] , j]的范围的回文子序列的长度。

②递推公式。

分两种情况,若s[i] == s[j],那么dp[i] [j] = dp[i+1] [j-1] + 2

​ 若s[i] != s[j], 那么也有两种情况,由于回文子序列可以不连续,只取s[i] 或者 s[j] 也有可能构成回文子序列。故只取s[i] 为 dp[i] [j-1],只取s[j] 为dp[i+1] [j],取这两种情况的最大值。

代码随想录训练营第五十七天_第3张图片

③初始化

根据递推公式,i不断+1,j不断-1,不断向中间靠拢,直到i = j,而这里就是需要初始化的地方,i = j为一个元素,一个元素也为回文子序列,所以赋值1。

④遍历顺序

代码随想录训练营第五十七天_第4张图片

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
        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];
    }
};

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