描述
字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置 所组成的新字符串。(例如,"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
解析
我们拿s = “babgbag”, t = “bag”来举例分析
-
我们依次确认s中有多少个"b"组合、”ba“组合、”bag“组合
-
ba组合=s中指针的位置之前已有的ba组合个数+b的个数
第一个a: ba组合=0(前面还没有ba组合)+1(前面有一个b)=1
第二个a: ba组合=1(前面有一个ba组合)+3(前面有三个b)=4 -
bag组合=s中指针的位置之前已有的bag组合个数+ba的组合个数
第一个g: bag组合=0(前面没有bag组合)+1(前面ba组合个数)=1
第二个g: bag组合=1(前面bag组合个数)+4(前面ba组合个数)=5
代码
public static int numDistinct(String s, String t) {
//sLength和tLength分别是两个字符串的长度
int sLength = s.length();
int tLength = t.length();
int[][] dp = new int[tLength + 1][sLength + 1];
//base case 边界条件
for (int j = 0; j <= sLength; j++) {
dp[0][j] = 1;
}
for (int i = 1; i <= tLength; i++) {
//注意此处j的开始位置是i
for (int j = i; j <= sLength; j++) {
//下面是递推公式
char chart = t.charAt(i - 1);
char charS = s.charAt(j - 1);
if (chart == charS) {
//如果字符串t的第i个字符和s的第j个字符一样, //那么有两种选择
int ij = dp[i - 1][j - 1];
int ij1 = dp[i][j - 1];
dp[i][j] = ij + ij1;
} else {
//如果字符串t的第i个字符和s的第j个字符不一样,
// 我们只能用字符串s的前j-1个字符来计算他包含的数量
dp[i][j] = dp[i][j - 1];
}
}
}
return dp[tLength][sLength];
}```