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];
    }
}