不同的子序列

题目来源:力扣115

解法思路:使用动态规划

定义 dp[i][j]为考虑 s 中 [0,i-1]个字符,t 中 [0,j-1] 个字符的匹配个数。

那么显然对于某个dp[i][j] 而言,从「最后一步」的匹配进行分析,包含两类决策:
1、不让 s[i] 参与匹配,也就是需要让 s 中 [0,i−1]个字符去匹配 t 中的 [0,j-1]字符。此时匹配值为 dp[i][j]

2、让 s[i] 参与匹配,这时候只需要让 s 中 [0,i−2]个字符去匹配 t 中的 [0,j−1]字符即可,同时满足 s[i-1]=t[j-1]。此时匹配值为 dp[i-1][j]

最终 dp[i][j] 就是两者之和。

初始化:
根据dp[i][j]的定义需要初始化 dp[i][0]和dp[0][j]
再看看dp[i][j]的定义可以知道 dp[i][0] 全为1;dp[0][j]全为0;dp[0][0]为1

完整代码

点击查看代码
class Solution {
public:
    int numDistinct(string s, string t) {
        //因为要求的是 s字符串中有多少个t,所以s字符串长度应该大于等于t字符串长度
        if(s.size() < t.size()) return 0;

        //vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));
        vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1));
        //dp[i][j] 表示 s串中以第i-1为结尾的字符串中包含 t串中到第j-1 为结尾的字符串个数
        //初始化
        for(int i=1;i<s.size();i++)    
            dp[i][0] = 1;   
        for(int j=1;j<t.size();j++)
            dp[0][j] = 0;
        dp[0][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-1] + dp[i-1][j];
                    //dp[i-1][j-1]表示使用s[i-1]
                    //dP[i-1][j]表示不使用s[i-1]
                }else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        return dp[s.size()][t.size()];
    }
};
posted @ 2024-05-06 15:22  go__Ahead  阅读(3)  评论(0编辑  收藏  举报