Given two strings s t s t
and
, return the number of distinct subsequences of
which equals
.
A string's subsequence is a new string formed from the original string by deleting some (can be none) of the characters without disturbing the remaining characters' relative positions. (i.e.,
"ACE"
is a subsequence of "ABCDE"
while "AEC"
is not).
It is guaranteed the answer fits on a 32-bit signed integer.
Example 1:
Input: s = "rabbbit", t = "rabbit"
Output: 3
Explanation:
As shown below, there are 3 ways you can generate "rabbit" from S.
rabbbit rabbbit rabbbit
Example 2:
Input: s = "babgbag", t = "bag"
Output: 5
Explanation:
As shown below, there are 5 ways you can generate "bag" from S.
babgbag babgbag babgbag babgbag babgbag
Constraints:
-
0 <= s.length, t.length <= 1000
-
s
consist of English letters.t
不同的子序列。
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)
题目数据保证答案符合 32 位带符号整数范围。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/distinct-subsequences
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是二维DP。我们首先创建一个二维数组,长度是 int[][] dp = new int[s.length() + 1][t.length() + 1]。+1 的部分是DP类型的题的经典操作,这个DP数组的含义是当 S 以 i 结尾,T 以 j 结尾的时候,满足题意的subsequence的个数是多少。
这里有几个重点需要提及
- 首先如果 T 为空的时候,因为一个空串是任何非空字符串的 subsequence 所以 dp[i][0] = 1
- 如果 T 不为空,又分如下两种情况,我们用这个例子理解,S = ABCC, T = ABC
- 如果s.charAt(i - 1) == t.charAt(j - 1),也就是两边字母相同的时候,dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1]。比如例子中如果S和T都走到了各自最后的字母C的时候,这里有匹配,需要比较的是ABCC中含有多少个不同的ABC,这里分两种情况
- 如果我们考虑使用当前这个匹配,我们看一下前面的子串 ABC 和 AB 的匹配情况,对应dp[i - 1][j - 1]
- 如果不使用当前这个匹配,也就是说 S 中不包含标红的 C 的时候,我们看一下 S = ABC 里面有多少能有多少subsequence能匹配 T,对应dp[i - 1][j]
- 把如上这两种情况加起来,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
- 如果s.charAt(i - 1) != t.charAt(j - 1),也就是当前字母不匹配的情况下,我们只需要看 dp[i][j - 1]
- 如果s.charAt(i - 1) == t.charAt(j - 1),也就是两边字母相同的时候,dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1]。比如例子中如果S和T都走到了各自最后的字母C的时候,这里有匹配,需要比较的是ABCC中含有多少个不同的ABC,这里分两种情况
时间O(mn)
空间O(mn)
1 class Solution {
2 public static int numDistinct(String s, String t) {
3 int[][] dp = new int[s.length() + 1][t.length() + 1];
4 // corner case, if T is an empty string
5 for (int i = 0; i < s.length(); i++) {
6 dp[i][0] = 1;
7 }
8
9 for (int i = 1; i <= s.length(); i++) {
10 for (int j = 1; j <= t.length(); j++) {
11 if (s.charAt(i - 1) == t.charAt(j - 1)) {
12 dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
13 } else {
14 dp[i][j] = dp[i - 1][j];
15 }
16 }
17 }
18 return dp[s.length()][t.length()];
19 }
20 }