leetcode—115. 不同的子序列

3 篇文章 0 订阅

115. 不同的子序列

给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

题目数据保证答案符合 32 位带符号整数范围。

示例 1:

输入:s = "rabbbit", t = "rabbit"
输入:3

解析:

重点在这个 “选”,s 串有哪些选择,做出不同的选择会带来什么状态。

s = babgbag,t = bag为例,末尾字符相同,于是 s 有两种选择:用s[s.length-1]去匹配掉t[t.length-1],问题规模缩小:继续考察babgba和ba

不这么做,但t[t.length-1]需要被匹配,则在babgba中找匹配,考察babgba和bag

image.png

图片来源:https://leetcode-cn.com/problems/distinct-subsequences/solution/shou-hua-tu-jie-xiang-jie-liang-chong-ji-4r2y/

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

当s[i]和t[j]相等时,一共就只有两种选择,一种是s[i]和t[j]进行匹配,另外一种是s[i]和t[j]不匹配,这两种情况相加就是全集。

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

所以dp状态方程如下:

s[i]==t[j],dp[i][j] = dp[i-1][j-1]+dp[i-1][j]

s[i]!=t[j],dp[i][j] = dp[i-1][j];

 

dp初始化

dp[i][0]:t为空串,此时 s 为了匹配它,方式只有1种:删光自己所有的字符,变成空串。(或 s 也是空串,什么都不做就匹配了,方式数也是1)
      因此dp[i][0]都是1。
dp[0][j]:s 为空串,但 t 不是,s 怎么样也匹配不了 t,方式数为 0
      因此dp[0][j]都是0。

class Solution {
public int numDistinct(String s, String t) {
        int n = s.length();
        int m = t.length();
        int [][] dp = new int[n+1][m+1];
        for(int i=0;i<n+1;i++){
            dp[i][0]=1;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1]+dp[i-1][j];
                }
                else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        return dp[n][m];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值