动态规划五部曲:
1、确定dp数组及其下标含义
dp[i][j]:以s[i-1]结尾的s子序列中出现以t[j-1]结尾的t的个数
2、确定递推式
当s[i-1] == t[j-1] 一部分用s[i-1]来匹配 dp[i][j] = dp[i-1][j-1]
一部分不用s[i-1]来匹配 dp[i][j] = dp[i-1][j]
所以dp[i][j] = dp[i-1][j-1]+dp[i-1][j]
当s[i-1] != t[j-1] dp[i][j] = dp[i-1][j];
3、初始化
for(int i = 0;i<=s.length();i++){
dp[i][0] = 1;
}
for(int j = 1;j<=t.length();j++){
dp[0][j] = 0;
}
4、确定遍历顺序
从前往后
5、举例推导dp数组
1 1 1 1 1 1 1
0 1 0 0 0 0 0
0 1 1 0 0 0 0
0 1 1 1 0 0 0
0 1 1 2 1 0 0
0 1 1 3 3 0 0
0 1 1 3 3 3 0
0 1 1 3 3 3 3
题解:
class Solution {
public:
int numDistinct(string s, string t) {
//dp[i][j]:以s[i-1]结尾的s子序列中出现以t[j-1]结尾的t的个数
//确定递推公式
//当s[i-1] == t[j-1] 一部分用s[i-1]来匹配 一部分不用s[i-1]来匹配
//dp[i][j] = dp[i-1][j-1]+dp[i-1][j]
//当s[i-1] != t[j-1] dp[i][j] = dp[i-1][j];
//定义dp数组
vector<vector<uint64_t>> dp(s.length()+1,vector<uint64_t>(t.length()+1));
//初始化
for(int i = 0;i<=s.length();i++){
dp[i][0] = 1;
}
for(int j = 1;j<=t.length();j++){
dp[0][j] = 0;
}
//计算dp
for(int i = 1;i<=s.length();i++){
for(int j = 1;j<=t.length();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[s.length()][t.length()];
}
};