You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
2.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package 01.mca_test;
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]
// 可能性1S[...i]的所有子序列中都不以s[i]结尾则dp[i][j]肯定包含dp[i-1][j]
// 可能性2S[...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));
}
}