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
.
参考:http://blog.csdn.net/abcbc/article/details/8978146
自己已经推到近在咫尺,但是最终还是错了。
虽然近在咫尺,但是说明了思路还是有问题。
我推着推着发现和最大m子段问题的递推略类似,但是
"aabb" "ab"
\\
这个用例让我发现我所推导的公式其实并不正确…
尴尬….虽然也推了这个矩阵
r a b b b i t
1 1 1 1 1 1 1 1
r 0 1 1 1 1 1 1 1
a 0 0 1 1 1 1 1 1
b 0 0 0 1 2 3 3 3
b 0 0 0 0 1 3 3 3
i 0 0 0 0 0 0 3 3
t 0 0 0 0 0 0 0 3
说明其实思路有问题的…
还是要弄清楚这个问题究竟要怎么求,而不是单纯拿一个矩阵找规律。
很显然,t[i]!=s[j] 时,dp[i][j]=dp[i][j-1],需要找后面能匹配多少
t[i]==s[j]的时候,应当考虑s[0~j-1]能否匹配t[0..i] and s[0~j-1]能否匹配t[0..i-1]
拿ab和aabb来说,i=2 && j=3时,考虑aa匹配ab aa匹配a
i=2 && j==4 时,考虑aab匹配 ab , aab匹配a
用状态来说,也就是,t[i]这个数据加入前后,增加了一个dp[i][j-1]种可能匹配
class Solution {
public:
int numDistinct(string s, string t) {
int m=t.size();
int n=s.size();
s.insert(s.begin(),'#');
t.insert(t.begin(),'#');
int dp[m+1][n+1];
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int j=1;j<=n;j++) dp[0][j]=1;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(t[i]!=s[j])
dp[i][j]=dp[i][j-1];
else{
//递推公式如此简单...
dp[i][j]=dp[i][j-1]+dp[i-1][j-1];
// if(i==j) dp[i][j]=dp[i-1][j-1];
// else{
// int maxV=dp[i-1][i];
// for(int k=i;k<j;k++)
// maxV=max(maxV,dp[i-1][k]);
// if(dp[i][j-1]>0)
// dp[i][j]=max(maxV+1,dp[i][j-1]+1);
// else
// dp[i][j]=max(maxV,dp[i][j-1]+1);
// }
}
}
}
// for(int i=1;i<=m;i++){
// for(int j=1;j<=n;j++)
// printf("%d ",dp[i][j]);
// printf("\n");
// }
// printf("\n");
return dp[m][n];
}
};