Given a string S and a string T, count the number of distinct subsequences of S which equals T.
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).
Here is an example:
S = "rabbbit", T = "rabbit"
Return 3.
題意:有兩個字符串S和T,求S中有多少個子字符串和T相等。
思路:
可以暴力的枚舉S的所有子串然后和T比較,時間復雜度將會是S長度的階乘。
動態規劃的方法,用dp[i][j]表示S從0到j有多少個子串和T從0到i相等。
舉個栗子:S是abb,T是ab,下面用一個矩陣表示
T/S 空 a b b
空 1 1 1 1
a 0 1 1 1
b 0 0 1 2
當T是空串的時候,S任意的前綴串都有空串和T相等,所以第一行都是1.
當Si和Tj字符不等時,我們只能看S的0到j-1和T有多少個匹配,即dp[i][j] = dp[i][j-1];
當Si和Tj字符相等時,假設是例子中最后ab和abb的情況:
第一個角度是可以把最后的兩個b看作是一起后加上去的,那么ab和abb的匹配數等于a和ab的匹配數,即dp[i][j] += dp[i-1][j-1];
第二個角度是可以把abb最后一個b視作替換掉它之前的b,那么ab和abb的匹配數等于ab和ab的匹配樹,即dp[i][j] += dp[i][j-1]。
所以dp[i][j] = dp[i-1][j-1] + dp[i][j-1]。
public int numDistinct(String s, String t) {
if (s == null) {
return 0;
}
if (t == null) {
return 1;
}
int slen = s.length();
int tlen = t.length();
int[][] dp = new int[tlen][slen];
for (int i = 0; i <= slen; i++) {
dp[0][i] = 1;
}
for (int i = 1; i <= tlen; i++) {
for (int j = 1; j <= slen; j++) {
if (s.charAt(j) == t.charAt(i)) {
dp[i][j] = dp[i-1][j-1] + dp[i][j-1];
} else {
dp[i][j] = dp[i][j-1];
}
}
}
return dp[tlen][slen];
}