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];
}
}