package class17; // 测试链接 : https://leetcode-cn.com/problems/21dk04/ public class Code04_DistinctSubseq { public static int numDistinct1(String S, String T) { char[] s = S.toCharArray(); char[] t = T.toCharArray(); return process(s, t, s.length, t.length); } public static int process(char[] s, char[] t, int i, int j) { if (j == 0) { return 1; } if (i == 0) { return 0; } int res = process(s, t, i - 1, j); if (s[i - 1] == t[j - 1]) { res += process(s, t, i - 1, j - 1); } return res; } // S[...i]的所有子序列中,包含多少个字面值等于T[...j]这个字符串的子序列 // 记为dp[i][j] // 可能性1)S[...i]的所有子序列中,都不以s[i]结尾,则dp[i][j]肯定包含dp[i-1][j] // 可能性2)S[...i]的所有子序列中,都必须以s[i]结尾, // 这要求S[i] == T[j],则dp[i][j]包含dp[i-1][j-1] public static int numDistinct2(String S, String T) { char[] s = S.toCharArray(); char[] t = T.toCharArray(); // dp[i][j] : s[0..i] T[0...j] // dp[i][j] : s只拿前i个字符做子序列,有多少个子序列,字面值等于T的前j个字符的前缀串 int[][] dp = new int[s.length + 1][t.length + 1]; // dp[0][0] // dp[0][j] = s只拿前0个字符做子序列, T前j个字符 for (int j = 0; j <= t.length; j++) { dp[0][j] = 0; } for (int i = 0; i <= s.length; i++) { dp[i][0] = 1; } for (int i = 1; i <= s.length; i++) { for (int j = 1; j <= t.length; j++) { dp[i][j] = dp[i - 1][j] + (s[i - 1] == t[j - 1] ? dp[i - 1][j - 1] : 0); } } return dp[s.length][t.length]; } public static int numDistinct3(String S, String T) { char[] s = S.toCharArray(); char[] t = T.toCharArray(); int[] dp = new int[t.length + 1]; dp[0] = 1; for (int j = 1; j <= t.length; j++) { dp[j] = 0; } for (int i = 1; i <= s.length; i++) { for (int j = t.length; j >= 1; j--) { dp[j] += s[i - 1] == t[j - 1] ? dp[j - 1] : 0; } } return dp[t.length]; } public static int dp(String S, String T) { char[] s = S.toCharArray(); char[] t = T.toCharArray(); int N = s.length; int M = t.length; int[][] dp = new int[N][M]; // s[0..0] T[0..0] dp[0][0] dp[0][0] = s[0] == t[0] ? 1 : 0; for (int i = 1; i < N; i++) { dp[i][0] = s[i] == t[0] ? (dp[i - 1][0] + 1) : dp[i - 1][0]; } for (int i = 1; i < N; i++) { for (int j = 1; j <= Math.min(i, M - 1); j++) { dp[i][j] = dp[i - 1][j]; if (s[i] == t[j]) { dp[i][j] += dp[i - 1][j - 1]; } } } return dp[N - 1][M - 1]; } public static void main(String[] args) { String S = "1212311112121132"; String T = "13"; System.out.println(numDistinct3(S, T)); System.out.println(dp(S, T)); } }