代码随想录算法训练营第五十五天| 392. 判断子序列、115.不同的子序列

392 判断子序列

题目链接:392
思路:

  • 定义dp[i][j]代表t[0,j-1]的子序列中是否出现s[0,i-1]
  • t[j-1]!=s[i-1]时,以t[j-1]结尾的子序列不可能等于s[0,i-1],因此s[0,i-1]是否出现等价于在t[0,j-2]的子序列中是否出现,即dp[i][j]=dp[i][j-1];当t[j-1]==s[i-1]时,只要在t[0,j-2]中出现s[0,i-2],此时再加上t[j-1],则s[0,i-1]一定出现,因此dp[i][j]=dp[i-1][j-1]
  • dp[0][j]t[0,j-1]的子序列中是否出现空串,因此是truedp[i][0]为空串的子序列中是否出现s[0,i-1],因此为falsedp[0][0]代表空串的子序列中是否出现空串,为true

代码:

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

115 不同的子序列

题目链接:115
思路:

  • 定义dp[i][j]代表s[0,i-1]中,序列t[0,j-1]出现的次数。
  • s[i-1]!=t[j-1]时,存在s[i-1]的子序列一定以s[i-1]结尾,因此不可能与t[0,j-1]相同,此时t[0,j-1]出现的次数等于在s[0,i-2]的子序列中出现的次数,即dp[i-1][j]。当s[i-1]==t[j-1]时,t[0,j-1]除了在s[0,i-2]的子序列中出现,还可能是在s[0,i-2]中出现的t[0,j-2]拼上s[i-1],即dp[i][j]=dp[i-1][j]+dp[i-1][j-1]
  • dp[i][0]s[0,i-1]的子序列中空串的个数,因此是1;dp[0][j]为空串的子序列中t[0,j-1]的个数,因此为0;dp[0][0]代表空串的子序列中空串的个数,为1。

代码:

class Solution {
public:
    int numDistinct(string s, string t) {
        vector<vector<unsigned int>> dp(s.size()+1, vector<unsigned int>(t.size()+1, 0));
        for (int i=0; i<=s.size(); ++i) {
            dp[i][0] = 1;
        }
        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]+dp[i-1][j-1];
                else dp[i][j] = dp[i-1][j];
            }
        }
        return dp[s.size()][t.size()];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值