392 判断子序列
题目链接:392
思路:
- 定义
dp[i][j]
代表t[0,j-1]
的子序列中是否出现s[0,i-1]
。 - 当
t[j-1]!=s[i-1]
时,以t[j-1]
结尾的子序列不可能等于s[0,i-1]
,因此s[0,i-1]
是否出现等价于在t[0,j-2]
的子序列中是否出现,即dp[i][j]=dp[i][j-1]
;当t[j-1]==s[i-1]
时,只要在t[0,j-2]
中出现s[0,i-2]
,此时再加上t[j-1]
,则s[0,i-1]
一定出现,因此dp[i][j]=dp[i-1][j-1]
。 dp[0][j]
为t[0,j-1]
的子序列中是否出现空串,因此是true
;dp[i][0]
为空串的子序列中是否出现s[0,i-1]
,因此为false
;dp[0][0]
代表空串的子序列中是否出现空串,为true
。
代码:
class Solution {
public:
bool isSubsequence(string s, string t) {
vector<vector<bool>> dp(s.size()+1, vector<bool>(t.size()+1, false));
for (int j=0; j<=t.size(); ++j) {
dp[0][j] = true;
}
for (int i=1; i<=s.size(); ++i) {
for (int j=1; j<=t.size(); ++j) {
if (s[i-1] == t[j-1]) dp[i][j] = dp[i-1][j-1];
else dp[i][j] = dp[i][j-1];
}
}
return dp[s.size()][t.size()];
}
};
115 不同的子序列
题目链接:115
思路:
- 定义
dp[i][j]
代表s[0,i-1]
中,序列t[0,j-1]
出现的次数。 - 当
s[i-1]!=t[j-1]
时,存在s[i-1]
的子序列一定以s[i-1]
结尾,因此不可能与t[0,j-1]
相同,此时t[0,j-1]
出现的次数等于在s[0,i-2]
的子序列中出现的次数,即dp[i-1][j]
。当s[i-1]==t[j-1]
时,t[0,j-1]
除了在s[0,i-2]
的子序列中出现,还可能是在s[0,i-2]
中出现的t[0,j-2]
拼上s[i-1]
,即dp[i][j]=dp[i-1][j]+dp[i-1][j-1]
。 dp[i][0]
为s[0,i-1]
的子序列中空串的个数,因此是1;dp[0][j]
为空串的子序列中t[0,j-1]
的个数,因此为0;dp[0][0]
代表空串的子序列中空串的个数,为1。
代码:
class Solution {
public:
int numDistinct(string s, string t) {
vector<vector<unsigned int>> dp(s.size()+1, vector<unsigned int>(t.size()+1, 0));
for (int i=0; i<=s.size(); ++i) {
dp[i][0] = 1;
}
for (int i=1; i<=s.size(); ++i) {
for (int j=1; j<=t.size(); ++j) {
if (s[i-1] == t[j-1]) dp[i][j] = dp[i-1][j]+dp[i-1][j-1];
else dp[i][j] = dp[i-1][j];
}
}
return dp[s.size()][t.size()];
}
};