Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
-
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
-
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)
-
题目数据保证答案符合 32 位带符号整数范围。
示例 1
输入:s = "rabbbit", t = "rabbit"
输出:3
解释:
如下图所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。
rabbbit
rabbbit
rabbbit
示例 2
输入:s = "babgbag", t = "bag"
输出:5
解释:
如下图所示, 有 5 种可以从 s 中得到 "bag" 的方案。
babgbag
babgbag
babgbag
babgbag
babgbag
思路分析
- 当遇到字符串匹配相关问题时,我们可能会想到滑动窗口、动态规划等等。本题目要求在 串中找出可以组成 串的数量。所以可以以 串的每个字符为基准,它对应的 串的字符有相同和不相同两种状态,可以根据前一状态进行转移到当前状态。
- 假设 对应位置为 , 对应位置为 。
- 当对应位置字符 相同 时,我们只需要把 中 子串的数量加上 中 子串的数量转移到当前状态。表达式为: 。
- 当对应位置字符 不相同 时,只需把 中 子串数量转移到当前状态。表达式为: 。
AC 代码
class Solution {
public int numDistinct(String s, String t) {
char[] cs = s.toCharArray();
char[] ct = t.toCharArray();
int ns = cs.length;
int nt = ct.length;
int[][] dp = new int[nt + 1][ns + 1];
Arrays.fill(dp[0],1);
for (int i = 1; i <= nt; i++) {
for (int j = 1; j <= ns; j++) {
if (ct[i - 1] == cs[j - 1]) {
dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
} else {
dp[i][j] = dp[i][j - 1];
}
}
}
return dp[nt][ns];
}
}
总结
- 动态规划的题就是这样,当想明白的时候,题目就 AC 得很快,反之不然。如果还有疑问的话可以点击 这里 。