Problem
Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).
Example
Given S = "rabbbit", T = "rabbit", return 3.
Challenge
Do it in O(n2) time and O(n) memory.
O(n2) memory is also acceptable if you do not know how to optimize memory.
Note
用动规方法做:
建立长度为m+1
和n+1
的二维dp
数组,dp[i][j]
表示S的第0到i位子串包含不同的T的第0到j位子串的个数。
初始化:当T的子串长度为0时,dp[i][0] = 1
;当S的子串长度为0时,dp[0][i] = 0
;当S和T子串都为0时,0包含0,故dp[0][0] = 1
。
两次循环S和T,若S的最后一位和T的最后一位不同,那么S增加一位不会增加更多的包含关系,即dp[i][j]
仍然等于dp[i-1][j]
。若S的最后一位和T的最后一位相等,最后的结果一定也包含S和T各减一位的结果,如S="abb"
,T="ab"
,所以dp[i][j]
包含dp[i-1][j-1]
,再与与dp[i-1][j]
相加。
见下面的例子。
0 A B C
0 1 0 0 0
C 1 0 0 0
A 1 1 0 0
B 1 1 1 0
B 1 1 2 0
B 1 1 3 0
C 1 1 3 3
Solution
public class Solution {
public int numDistinct(String S, String T) {
int m = S.length(), n = T.length();
if (m < n) return 0;
int[][] dp = new int[m+1][n+1];
for (int i = 0; i <= m; i++) dp[i][0] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = dp[i-1][j];
if (S.charAt(i-1) == T.charAt(j-1)) dp[i][j] += dp[i-1][j-1];
}
}
return dp[m][n];
}
}
One-dimension DP, O(n) space
public class Solution {
public int numDistinct(String s, String t) {
int m = s.length();
int n = t.length();
int[] dp = new int[n+1];
dp[0] = 1;
for (int i = 1; i <= m; i++) {
for (int j = n; j >= 1; j--) {
if (s.charAt(i-1) == t.charAt(j-1)) {
dp[j] += dp[j-1];
}
}
}
return dp[n];
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。