思路:
dp遍历是环环相扣,紧密相连的。
子数组、子串是连续的。子序列是不连续的。(看43、53两道题解里有说明)
递推公式和初始化有点不一样。
储备:
会把一些特殊的要求复制进来。方便检索。
问题重点:
1、题目要求:结果需要对 109 + 7 取模。
2、
例如: s:bagg 和 t:bag ,s[3] 和 t[2]是相同的,但是字符串s也可以不用s[3]来匹配,即用s[0]s[1]s[2]组成的bag。
当然也可以用s[3]来匹配,即:s[0]s[1]s[3]组成的bag。
所以当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
当s[i - 1] 与 t[j - 1]不相等时,dp[i][j]只有一部分组成,不用s[i - 1]来匹配(就是模拟在s中删除这个元素),即:dp[i - 1][j]
所以递推公式为:dp[i][j] = dp[i - 1][j];
dp[i][0]表示什么呢?
dp[i][0] 表示:以i-1为结尾的s可以随便删除元素,出现空字符串的个数。
那么dp[i][0]一定都是1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1。
再来看dp[0][j],dp[0][j]:空字符串s可以随便删除元素,出现以j-1为结尾的字符串t的个数。
那么dp[0][j]一定都是0,s如论如何也变成不了t。
最后就要看一个特殊位置了,即:dp[0][0] 应该是多少。
dp[0][0]应该是1,空字符串s,可以删除0个元素,变成空字符串t。
最后:
class Solution {
public:
int numDistinct(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<unsigned int>> dp(n+1,vector<unsigned int>(m+1,0));
//母串以i-1结尾,子串以j-1结尾,的子序列最大个数
for (int i=0;i<n;i++) dp[i][0]=1;//子串是空串。母串都是1
for (int j=1;j<m;j++) dp[0][m]=0;//母串是空串,故无论多少都是0
//从第一个开始比对
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;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];//沿用上一层循环的
}
}
return dp[n][m];
}
};


被折叠的 条评论
为什么被折叠?



