115.不同的子序列

115.不同的子序列

题目

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

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

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

示例 1:

输入:s = "rabbbit", t = "rabbit"
输出:3
解释:
如下图所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。
rabbbit
rabbbit
rabbbit

示例 2:

## babgbag输入:s = "babgbag", t = "bag"
输出:5
解释:
如下图所示, 有 5 种可以从 s 中得到 "bag" 的方案。 
babgbag
babgbag
babgbag
babgbag
babgbag

提示:

1 <= s.length, t.length <= 1000
s 和 t 由英文字母组成

题解

首先这道题是多阶段决策问题,并且不求具体解,只求最优解,尝试利用动态规划求解。

dp数组及其下标含义
一般求什么设什么,这里求个数,那么dp数组就表示为个数。

dp[i][j]:[0,i-1]位置的子字符串t在[0,j-1]位置的字符串s中出现的个数

dp数组的递推式

是用子串去s字符串里匹配。

当S[j] == T[i]时,此时有两种前置状态可以跳到dp[i][j],
一是让i和j都前进一步,因为他们相等,dp[i][j] = dp[i-1][j-1]
二是只让j前进一步(这之前已经出现的t子串已经出现的次数),所以为dp[i][j] = dp[i-1][j-1] + dp[i][j-1]

当S[j] != T[i]时,只能j前进了,所以为dp[i][j] = dp[i][j-1],a在ab中出现了一次,a在abb中也是出现了一次

dp数组初始化

当i=0时,需要初始化1,这样才可以保证,因为空集是所有字符串子集, 所以我们第一行都是 1

代码

class Solution {
    public int numDistinct(String s, String t) {
        int sLen = s.length();
        int tLen = t.length();
        if(tLen>sLen)return 0;
        int dp [] [] = new int [tLen+1][sLen+1];
         for(int j = 0; j <= s.length(); j++){
            dp[0][j] = 1;
        }
        for(int i=1;i<=tLen;i++){
            for(int j=1;j<=sLen;j++){
                if(t.charAt(i-1) == s.charAt(j-1))
					 dp[i][j] = dp[i-1][j-1] + dp[i][j-1];
               else
                    dp[i][j] = dp[i][j-1];
            }
        }
            return dp [tLen] [sLen];
    }
}
posted @ 2021-11-12 21:14  rananie  阅读(48)  评论(0编辑  收藏  举报