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
.
还是如何定义状态的问题。
学会如何去重新定义一个问题,这里描述的是用S去匹配T有多少种方法。也就是用S[0....S.len-1]去匹配T[0.....T.len-1]有多少种方法。
所以,可以定义状态dp[i][j]表示,用S[0~i]去匹配T[0~j]有多少种方法,dp[S.len-1][T.len-1]即为所求。
接下来讨论状态转移问题。
dp[i][j] 可由dp[i-1][j-1]和dp[i][j-1]得到。为什么呢?针对s[i]和t[i]可以进行如下讨论:
① 若s[i] != t[i], 不用说,dp[i][j] = dp[i][j-1]
② 若s[i] == t[j],可以选择用s[i] 去匹配 t[j], 也可以选择不匹配。此时, dp[i][j] = dp[i-1][j-1] + dp[i][j-1]
public int numDistinct(String S, String T) {
if(S == null || (S.length() == 0 && T.length() != 0) || T == null || (T.length() > S.length())) return 0;
if(S.length() != 0 && T.length() == 0)
return 1;
int lens = S.length();
int lent = T.length();
int[][] dp = new int[lens][lent];
dp[0][0] = S.charAt(0) == T.charAt(0) ? 1 : 0;
for(int i = 1; i < lens; i++){
if(S.charAt(i) == T.charAt(0))
dp[i][0] = dp[i-1][0] + 1;
else
dp[i][0] = dp[i-1][0];
}
for(int i = 1; i < lens; i++)
for(int j = 1; j < lent; j++){
if(S.charAt(i) == T.charAt(j))
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
else
dp[i][j] = dp[i-1][j];
}
return dp[lens-1][lent-1];
}