115. 不同的子序列【动态规划】【大彻大悟包教包会】

✅做题思路or感想

这道困扰我一刷好久的题终于在二刷的今天彻底理解了,通透啊!

这道题的难点在于递推公式初始化

首先可以把题目按照自己的意思更大白话的复述一遍

  • 题面:找 s的子序列中t出现的次数
  • 复述:在s挑选字符来组成t,求这个操作有几种方法

dp数组含义

dp[i][j]表示[0, i - 1][0, j - 1]的区间上的挑选字符使之匹配的方法个数

💡递推公式

这里从最后一步开始思考。以s = babat = ba为例子,当最后一个字符a相同时,有两种选择(从最后一步思考)

  • s最后一位可以把t的最后一位匹配掉,则下一步要缩短匹配范围,去匹配bab b,即有dp[i - 1][j - 1]
  • 因为s是长的一方,s里面除了最后一位外可能还有其他的at的最后一位a匹配,所以这里放弃s的最后一位,缩短s的搜索范围继续匹配t的最后一位,所以有dp[i - 1][j]
  • 最后因为求的是方法数,所以要把这两种可能都加起来,故有dp[i][j] = dp[i - 1][j - 1], dp[i - 1][j]

而当s最后一个字符匹配不掉t的最后一个字符,则s再向后面匹配便是了,故有dp[i][j] = dp[i - 1][j]

综上

if (s[i - 1] == t[j - 1]) {
    dp[i][j] = dp[i - 1][j - 1]	//s[i - 1]匹配掉了t[j - 1]
        + dp[i - 1][j];	//s[i - 1]没有匹配掉t[j - 1]
} else {
    dp[i][j] = dp[i - 1][j];	//s[i - 1]没有匹配掉t[j - 1]
}

初始化

这种字符串问题的初始化一定要联想两边是空字符串的时候的情况

  • s是空字符串时,从s中挑不出字符组成t,所以这种情况的方法数为0,即是dp[0][j] = 0。而例外就是如果t也是空字符串,则有一种方法可以让他们匹配:什么也不做(认真),所以dp[0][0] = 1,这点特别重要
  • t是空字符串时,从s中挑字符组成t只有一种方法:什么也不做(认真),所以这种情况的方法数为1,即dp[i][0] = 1

遍历顺序

从递推公式知从小推大,故正序遍历

class Solution {
public:
    int numDistinct(string s, string t) {
        //这里注意测试用例里有超出int范围的例子,所以这里扩大一下范围,选用unsigned int
        vector<vector<unsigned>>dp (s.size() + 1, vector<unsigned>(t.size() + 1, 0));
        //初始化dp[i][0] = 1的情况,另一种情况在创建数组的时候就默认为0了,所以不用再用一个for来初始化
        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 - 1] + dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[s.size()][t.size()];
    }
};

这一题能理解透彻真的不容易,大彻大悟的感觉就是舒服

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值