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).
Here is an example:
S = "rabbbit"
, T = "rabbit"
Return 3
.
解题分析:dfs可以做,但大数据超时。
动态规划,定义dp[i][j]为字符串i变换到j的变换方法。
如果S[i]==T[j],那么dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。意思是:如果当前S[i]==T[j],那么当前这个字母即可以保留也可以抛弃,所以变换方法等于保留这个字母的变换方法加上不用这个字母的变换方法。
如果S[i]!=T[i],那么dp[i][j] = dp[i-1][j],意思是如果当前字符不等,那么就只能抛弃当前这个字符。
递归公式中用到的dp[0][0] = 1,dp[i][0] = 0(把任意一个字符串变换为一个空串只有一个方法)
具体代码:
public class Solution {
public int numDistinct(String s, String t) {
int len1 = t.length();
int len2 = s.length();
//如果t的长度比s大,则肯定不符合,直接返回0
if(len1 > len2){
return 0;
}
int[][] f = new int[len1][len2];
for(int i = 0; i < len1; i++){
for(int j = i; j < len2; j++){
boolean flag = t.charAt(i) == s.charAt(j);
//填充第一行元素
if(i == 0){
//如果字符相等,则在前一个字符数的基础上加1
//不相等则是直接等于前1个字符
if(j == 0){//如果是第一个元素相等,就是1个
f[i][j] = flag ? 1:0;
}else{
f[i][j] = flag ? f[i][j-1] + 1 : f[i][j-1];
}
}
//填充后面的行
else{
//如果字符相等,则看左边数据相加;
if(flag){
f[i][j] = f[i][j-1] + f[i-1][j-1];
}else{
//字符不相等,则等于字符左边数据,也即数量保持不变
f[i][j] = f[i][j-1];
}
}
}
}
return f[len1-1][len2-1];
}
}