不同的子序列
给定字符串 S 和 T, 计算 S 的所有子序列中有多少个 T.
子序列字符串是原始字符串删除一些(或零个)字符之后得到的字符串, 并且要求剩下的字符的相对位置不能改变. (比如 “ACE” 是 ABCDE 的一个子序列, 而 “AEC” 不是)。
注意事项:
数组A的长度不超过5000,每个元素的大小不超过5000
样例 1:
输入:
S = "rabbbit", T = "rabbit"
输出:
3
解释:
你可以删除 S 中的任意一个 'b', 所以一共有 3 种方式得到 T.
样例 2:
输入:
S = "abcd", T = ""
输出:
1
解释:
只有删除 S 中的所有字符这一种方式得到 T
解答:
定义dp[i][j]为 S长度为i,T长度为j时,S含有子序列T的个数。
对于末尾字符:
若相等,则:dp[i][j] = dp[i-1][j-1] + dp[i-1][j]{i>j},即要么S[i]作为T[j]的匹配,要么S[i]不匹配
否则:dp[i][j] = dp[i-1][j]{i>j}
class Solution {
public:
/**
* @param S: A string
* @param T: A string
* @return: Count the number of distinct subsequences
*/
int numDistinct(string &S, string &T) {
// write your code here
/*
定义dp[i][j]为 S长度为i,T长度为j时,S含有子序列T的个数。
对于末尾字符:
若相等,则:dp[i][j] = dp[i-1][j-1] + dp[i-1][j]{i>j},即要么S[i]作为T[j]的匹配,要么S[i]不匹配
否则:dp[i][j] = dp[i-1][j]{i>j}
*/
if(S.empty() && T.empty()){
return 0;
}
if(T.empty()){
return 1;
}
int m = S.size() + 1;
int n = T.size() + 1;
int **dp = new int*[m];
for (int i = 0; i < m; i++) {
dp[i] = new int[n];
for (int j = 0; j < n; j++) {
dp[i][j] = 0;
}
}
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
for (int i = 0; i < n; i++) {
dp[0][i] = 0;
}
for (int i = 1, j = 1; i < m && j < n; i++, j++) {
if(S.compare(0, i, T, 0, j) == 0){
dp[i][j] = 1;
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < i && j < n; j++) {
if(S[i-1] == T[j-1]){
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
}
else{
dp[i][j] = dp[i-1][j];
}
}
}
int result = dp[m-1][n-1];
for (int i = 0; i < m; i++) {
delete[] dp[i];
}
delete[] dp;
return result;
}
};