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.

102 lines
2.7 KiB

2 years ago
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]
// 可能性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));
}
}