Distinct Subsequences
Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE"
is a subsequence of "ABCDE"
while "AEC"
is not).
Here is an example:
S = "rabbbit"
, T = "rabbit"
Return 3
.
解题思路:
法1:递归 - DFS
使用深度优先搜索,深度为T的长度
每找到一个则计数,直到搜索结束
源码:
class Solution {
public:
void DFS(string &s, string &t, int deep, int is)
{
if (deep == t.size()) // 找到一个
{
cnt++;
return;
}
int end = s.size() - t.size() + is;
for (int i = is; i < end; ++i)
if (s[i] == t[deep])
DFS(s, t, deep+1, i+1); // 当前匹配,寻找下一个
return;
}
int numDistinct(string S, string T) {
// DFS
// 使用深度优先搜索,深度为T的长度
// 每找到一个则计数,直到搜索结束
if ((S.size() == 0) || (T.size() == 0))
return 0;
cnt = 0;
DFS(S, T, 0, 0);
return cnt;
}
private:
int cnt;
};
很不幸,以上方法超时。
法2:动态规划
分析:
重要的是找到转移方程
设f[i][j]表示 T的前j个字符 在 S的前i个字符 中出现的次数,则
/ 0, i = 0 || j = 0
f[i][j] = - f[i-1][j], (S[i] != T[j]) 只需要比较S的前i-1个 和 T的前j个
\ f[i-1][j] + f[i-1][j-1], (S[i] != T[j]) 前S的前i-1个出现 T的前j个的次数 + 前S的前i-1个出现 T的前j-1个的次数(加上最后一个字符,刚好凑成完整的字符串)
注意:
1. 字符串的下标处理
2. 当j=1时,若匹配,按照递推公式,前一部分是不考虑最后一个字符出现的次数,后一部分是包含最后一个出现的次数,其实是f[i-1][j-1] * 1,一定要加上本身的1
源码:
class Solution {
public:
int numDistinct(string S, string T) {
// DP
// 重要的是找到转移方程
// 设f[i][j]表示 T的前j个字符 在 S的前i个字符 中出现的次数,则
// / 0, i = 0 || j = 0
// f[i][j] = - f[i-1][j], (S[i] != T[j]) 只需要比较S的前i-1个 和 T的前j个
// \ f[i-1][j] + f[i-1][j-1], (S[i] != T[j]) 前S的前i-1个出现 T的前j个的次数 + 前S的前i-1个出现 T的前j-1个的次数(加上最后一个字符,刚好凑成完整的字符串)
if ((S.size() == 0) || (T.size() == 0))
return 0;
int lens = S.size();
int lent = T.size();
vector<vector<int> > f(lens+1, vector<int>(lent+1, 0));
for (int i = 1; i <= lens; ++i)
{
for (int j = 1; j <= lent; ++j)
{
if (S[i-1] != T[j-1]) // 注意下标
f[i][j] = f[i-1][j];
else
{
if (j == 1)
f[i][j] = f[i-1][j] + 1; // 加上最后一个字符(这里可以初始化f[i][0] = 1, 可是又不太符合逻辑,不便于理解)
else
f[i][j] = f[i-1][j] + f[i-1][j-1];
}
}
}
return f[lens][lent];
}
};