public class Subsequence {
public static int numDistinct(String s, String t) {
//二维数组
/*
int n=s.length();
int m=t.length();
int[][] dp=new int[n+1][m+1];//定义二维数组存储s的前i个字符中(子序列)出现t的前j个字符的个数,注意子序列可以是s通过删除得到的也可以不删除得到
//初始化
for(int i=0;i<=n;i++) dp[i][0]=1;//s的前i个子串中找到空串的个数都是1,因为可以通过删除的到空串
for(int j=1;j<=m;j++) dp[0][j]=0;//s的空串中含有t的前j个字符的个数为0
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s.charAt(i-1)==t.charAt(j-1)){
//如果s的第i个字符与t的第j个字符相等,那么分两种情况:
1、用第j个字符去匹配,那么就只计算s中前i-1个和t中前j-1个相等的个数
2、不用第j个字符去匹配,那么就计算s中前i-1个跟t中前j个相等的个数
dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
}else{
dp[i][j]=dp[i-1][j];//如果不相等,那么就是s中前i-1个和t中前j个相等的个数
}
}
}
return dp[n][m];
*/
//一维数组优化,我们可以发现dp[i][j]只跟dp[i-1]的元素有关,所以只需要利用一维数组存储之前的值即可
int n=s.length();
int m=t.length();
int[] dp=new int[m+1];//定义二维数组存储s的前i个字符中(子序列)出现t的前j个字符的个数,注意子序列可以是s通过删除得到的也可以不删除得到
dp[0]=1;//对应dp[0][0]
for(int j=1;j<=m;j++) dp[j]=0;//初始化,没有i,相当于空串中有t中前j个字符的个数,对应dp[0][j]=0;
for(int i=1;i<=n;i++){
for(int j=m;j>0;j--){
//由于当前的值需要用到上一轮i的j-1的值,是旧的值,但是如果j从小到大的话,那么j-1的值就会被更新为这一轮的j-1的值,会覆盖上一轮的j-1的值,
// 但是我们需要用到的j-1的值是上一轮i-1的而不是这一轮的,所以如果要用旧的j-1的值的话,那么就要让j从大到小就可以实现j-1的值是上一轮i-1的,没有更新的值
if(s.charAt(i-1)==t.charAt(j-1)){
//当s的第i个字符跟t的第j个字符相等时,那么就是上一轮的dp[j-1]的值和dp[j]的值相加,就看成是跟二维数组的两种情况:当利用t[j-1]和不利用t[j-1]去匹配的情况
dp[j]=dp[j-1]+dp[j];
}
}
}
return dp[m];
}
}