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

1.判断子序列 题392

①dp数组的定义

一般有两个序列,判断它们之间的关系应该用到二维dp数组。

这道题的思路应该是判断两个序列的最长公共子序列长度,若为s的长度,则s为t的公共子序列。

dp[i] [j] 为以i-1结尾的字符串s和以j-1结尾的字符串t的相同子序列的长度。

②递推公式

有两种情况,s[i-1]=t[j-1]时,dp[i] [j] = dp[i-1] [j-1] +1;

​ s[i-1]!=t[j-1]时,dp[i] [j] 应该同于以i-1为结尾的字符串s与以j-2为结尾的字符串t的相同字符串的长度,相当于删除了t中与s不相同的字符t[j-1],即dp[i] [j] = dp[i] [j-1] 。

③初始化和遍历顺序

初始化和遍历顺序看dp数组推导的方向,无意义的初始化为0。

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if(s.size() == 0){
            return true;
        }
        if(t.size() == 0){
            return false;
        }
        vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));
        for(int i = 1;i <= s.size();i++){
            for(int j = 1;j <= t.size();j++){
                if(s[i-1] == t[j-1]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                else{
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        if(dp[s.size()][t.size()] == s.size()){
            return true;
        }
        return false;
    }
};

2.不同的子序列 题115

①dp数组定义

dp[i] [j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i] [j]。

②递推公式

分两种情况,当s[i-1]=t[j-1]时,dp[i] [j]可以有两部分组成,一部分是用s[i - 1]来匹配,那么个数为dp[i - 1] [j - 1]。即不需要考虑当前s子串和t子串的最后一位字母,所以只需要 dp[i-1] [j-1];一部分是不用s[i - 1]来匹配,个数为dp[i - 1] [j],因为不用s[i - 1]来匹配,s以i-2为结尾的序列中可能有以j-1为结尾的t序列的相同子序列。

class Solution {
public:
    int numDistinct(string s, string t) {
        vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1));//int范围不够大
        for (int i = 0; i < s.size(); i++) dp[i][0] = 1;
        for (int j = 1; j < t.size(); j++) dp[0][j] = 0;
        for (int i = 1; i <= s.size(); i++) {
            for (int j = 1; j <= t.size(); j++) {
                if (s[i - 1] == t[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[s.size()][t.size()];
    }
};

你可能感兴趣的:(算法,动态规划,leetcode)