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
.
方法一:dfs,逐个字符串比较,大数据超时,
class Solution { int m_cnt; public: void dfs(const string & s, const string & t, int idx1, int idx2) { if(idx2 == t.size()) { m_cnt++; return; } if(idx1 == s.size()) return; for(int i = idx1; i < s.size(); i++) { if(s[i] == t[idx2]) dfs(s, t, i+1, idx2+1); } } int numDistinct(string S, string T) { m_cnt = 0; dfs(S,T,0,0); return m_cnt; } };
方法二:dp
设状态为 f(i, j),表示 T[0,i-1] 在 S[0,j-1] 里出现的次数。
如果T[i] != S[j],那么 f[i][j] = f[i][j-1] 意思就是和 T[0,i-1] 在 S[0,j-1] 里出现的次数相同。
如果T[i] == S[j],那么 f[i][j] = f[i][j-1] + f[i-1][j-1]
两种方法:t[i]是来源于s[j], 有 f[i-1][j-1] 种
t[i]是不来源于s[j],而是来源于s[0~i-1], 有 f[i][j-1] 种
时间复杂度O(m*n),空间O(m*n),不过可以用滚动数组,优化成O(m)
class Solution { public: int numDistinct(string s, string t) { vector<int> tmp(s.size() + 1, 0); vector<vector<int> > f(t.size()+1, tmp); //f[i][j] indicates nums that t[0,i-1] was converted by s[0,j-1] f[0][0] = 1; // null to null, only have one way for(int i = 1; i < s.size(); i++)// there is only one way that any string changed to null f[0][i] = 1; for(int i = 1; i < t.size(); i++)// there is no way that null to any string f[i][0] = 0; for(int j = 1; j <= s.size(); j++) { for(int i = 1; i <= t.size(); i++) { if(i > j) f[i][j] = 0; else { if(t[i-1] == s[j-1]) f[i][j] = f[i-1][j-1] + f[i][j-1]; else f[i][j] = f[i][j-1]; } } } return f[t.size()][s.size()]; } };