https://leetcode.cn/problems/21dk04/description/
定义dp[i][j]为主字符串长度为i时和匹配字符串长度为j时的匹配子序列,如果 最后一个字符不相等,必然是dp[i][j]=d[i-1][j],如果相等,这么去想,i-1时就已经有dp[i-1][j]个子序列匹配上j了,而dp[i-1][j-1]是匹配j-1的子序列,同事加一个相等的,匹配上j,就要加上dp[i-1][j-1];
const int N=1010;
unsigned long long dp[N][N];
#define ll long long
class Solution {
public:
int numDistinct(string s, string t) {
int n=s.length();
int m=t.length();
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
dp[i][j]=0;
for(int i=0;i<=n;i++) dp[i][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
dp[i][j]=dp[i-1][j];
if(s[i-1]==t[j-1])
{
dp[i][j]+=dp[i-1][j-1];
}
}
}
return dp[n][m];
}
};
对于优化空间,可以观察到dp[i][j]依赖于上方的格子和左上方的格子,那么可以从后往前滚动,滚动数组从i-1到i时,本身的值就是上方格子的,只需判断最后一个字符相不相等,相等就加上j-1的值(来到j时,j-1还没被更新过)
const int N=1010;
unsigned long long dp[N];
class Solution {
public:
int numDistinct(string s, string t) {
int n=s.length();
int m=t.length();
/* for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
dp[i][j]=0;*/
for(int i=0;i<=n;i++) dp[i]=0;
//for(int i=0;i<=n;i++) dp[i][0]=1;
dp[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=m;j>=1;j--)
{
/*dp[i][j]=dp[i-1][j];
if(s[i-1]==t[j-1])
{
dp[i][j]+=dp[i-1][j-1];
}*/
if(s[i-1]==t[j-1])
{
dp[j]+=dp[j-1];
}
}
}
return dp[m];
}
};