首页 > 代码库 > Distinct Subsequences
Distinct Subsequences
Dynamic Programming
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
.
题目大意:删除S中某些位置的字符可以得到T,总共有几种不同的删除方法
设S的长度为lens,T的长度为lent
算法1:递归解法,首先,从个字符串S的尾部开始扫描,找到第一个和T最后一个字符相同的位置k,那么有下面两种匹配:a. T的最后一个字符和S[k]匹配,b. T的最后一个字符不和S[k]匹配。a相当于子问题:从S[0...lens-2]中删除几个字符得到T[0...lent-2],b相当于子问题:从S[0...lens-2]中删除几个字符得到T[0...lent-1]。那么总的删除方法等于a、b两种情况的删除方法的和。递归解法代码如下,但是通过大数据会超时:
class Solution {public: int numDistinct(string S, string T) { // IMPORTANT: Please reset any member data you declared, as // the same Solution instance will be reused for each test case. return numDistanceRecur(S, S.length()-1, T, T.length()-1); } int numDistanceRecur(string &S, int send, string &T, int tend) { if(tend < 0)return 1; else if(send < 0)return 0; while(send >= 0 && S[send] != T[tend])send--; if(send < 0)return 0; return numDistanceRecur(S,send-1,T,tend-1) + numDistanceRecur(S,send-1,T,tend); }};
参考:http://www.cnblogs.com/TenosDoIt/p/3440022.html
http://yutianx.info/blog/2014/09/25/leetcode-distinct-subsequences.html
遇到这种两个串的问题,很容易想到DP。但是这道题的递推关系不明显。可以先尝试做一个二维的表int[][] dp,用来记录匹配子序列的个数(以S="rabbbit"
,T = "rabbit"
为例):
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的字符与S的字符是否匹配,dp[i][j] = dp[i][j - 1].就是说,假设S已经匹配了j - 1个字符,得到匹配个数为dp[i][j - 1].现在无论S[j]是不是和T[i]匹配,匹配的个数至少是dp[i][j - 1]。除此之外,当S[j]和T[i]相等时,我们可以让S[j]和T[i]匹配,然后让S[j - 1]和T[i - 1]去匹配。所以递推关系为:
dp[0][0] = 1; // T和S都是空串.
dp[0][1 ... S.length() - 1] = 1; // T是空串,S只有一种子序列匹配。
dp[1 ... T.length() - 1][0] = 0; // S是空串,T不是空串,S没有子序列匹配。
dp[i][j] = dp[i][j - 1] + (T[i - 1] == S[j - 1] ? dp[i - 1][j - 1] : 0).1 <= i <= T.length(), 1 <= j <= S.length()
实现代码:
#include<iostream>#include<string>using namespace std;class Solution {public: int numDistinct(string S, string T) { int slen=S.length(); int tlen=T.length(); if(tlen==0) return 1; if(slen==0&&tlen) return 0; int dp[slen+1][tlen+1]; dp[0][0]=1; int i,j; for(i=1;i<=slen;i++) dp[i][0]=1; for(i=1;i<=tlen;i++) dp[0][i]=0; for(i=1;i<=slen;i++) { for(j=1;j<=tlen;j++) { if(S[i-1]==T[j-1]) dp[i][j]=dp[i-1][j]+dp[i-1][j-1]; else dp[i][j]=dp[i-1][j]; } } return dp[slen][tlen]; }};int main(){ Solution s; string S="rabbbit"; string T="rabbit"; cout<<s.numDistinct(S,T)<<endl;}
Distinct Subsequences