代码随想录算法训练营第五十六天| 动态规划

Posted by Zhuoqun on March 10, 2023

647. 回文子串

这道题看了Carl的题解明白了。本题一大重点是确定遍历顺序:因为我们是一步步 从小到大来i到j之间是不是回文串,所以我们就不能从小到大 从左到右来遍历了。需要i从最大值,然后j从最小值,从左往右遍历。然后必须确保j要小于等于i才行。这个我学的不是很扎实,还需要再做一遍。

class Solution {
public:
    int countSubstrings(string s) {
        int s_length = s.length();
        int result = 0;
        vector<vector<bool>> dp(s.length(),vector<bool>(s.length(),false));

        for(int i=s_length-1; i>=0; i--){
            for(int j=i; j<s_length; j++){
                if(s[i] == s[j]){
                    if(j-i <= 1){
                        dp[i][j] = true;
                        result++;
                    }
                    else if(dp[i+1][j-1]){
                        dp[i][j] = true;
                            result++;
                    }
                }
            }
        }
        return result;
    }
};

516.最长回文子序列

真的是太聪明了。我一直没想明白如果目前的i到j之间的字符串本身如果不是整体的回文,其实就应该取dp[i + 1][j]和dp[i][j - 1]中最大的。这就是从小的数组到大的一步步推出来最大的回文子序列长度。

这道题我没自己写,但是明天应该自己写一遍。

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];
    }
};