持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)
题目数据保证答案符合 32 位带符号整数范围。
示例 1:
输入: s = "rabbbit", t = "rabbit"
**输出**:3
解释:
如下图所示, 有 3 种可以从 s 中得到"rabbit" 的方案。
**rabb**b**it**
**ra**b**bbit**
**rab**b**bit**
示例 2:
输入: s = "babgbag", t = "bag"
**输出**:5
解释:
如下图所示, 有 5 种可以从 s 中得到"bag" 的方案。
**ba**b**g**bag
**ba**bgba**g**
**b**abgb**ag**
ba**b**gb**ag**
babg**bag**
提示:
0 <= s.length, t.length <= 1000s和t由英文字母组成
思路
用m和n来表示s和t的长度,本题分为三种情况:
- 如果
s等于t,返回1, - 如果
m小于等于n,返回0, - 如果
m大于n,用动态规划求解。用数组dp[i][j]来保存s中前i个字符的子序列在t的前j个字符中出现的个数,则- 如果
s[i-1]不等于t[j-1],dp[i][j] = dp[i-1][j] - 如果
s[i-1]等于t[j-1],dp[i][j] = dp[i-1][j] + dp [i-1][j-1]
最后返回dp[m][n],初始状态dp[0][0] = 1,表示初始值两个空字符串匹配个数为1
- 如果
解题
/**
* @param {string} s
* @param {string} t
* @return {number}
*/
var numDistinct = function (s, t) {
if (s === t) return 1;
const m = s.length;
const n = t.length;
if (m <= n) return 0;
const dp = new Array(n + 1).fill(null).map(() => new Array(m + 1).fill(0));
for (let i = 0; i <= m ; i++) {
dp[0][i] = 1;
}
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
dp[i][j] = dp[i][j - 1];
if (t[i - 1] === s[j - 1]) {
dp[i][j] += dp[i - 1][j - 1];
}
}
}
return dp[n][m];
};