LeetCode Distinct Subsequences

来源:互联网 发布:研究所20升级数据 编辑:程序博客网 时间:2024/06/07 20:47



https://oj.leetcode.com/problems/distinct-subsequences/


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的不同子序列中与字符串T相同子序列的数量。

更深入理解就是:字符串S在不改变字符顺序的情况下,可以去掉其中的任意个数字符得到T。有多少种去法。


这类找子串的题目一般就是动态规划的题目,所以下面使用动态规划来完成。

需要考虑:

(1)当字符串S的长度小于字符串T时吗,也就是S中不存在T子序列,所以返回0.


(2)然后考虑动态规划的状态转移方程:

        

         1)首先定义dp[i][j]表示S的前i个字符的子序列中与T的前j个字符匹配的数目。很明显d[i][0]=1;因为J=0表示T是空串,此时S   的任何一个子串都可以通过去掉所有的字符,这一种方式(d[i][0] = 1的原因)来与T匹配。当然d[0][j]=0(j>=1)这也很明显,原因就是如果S为空串,那么S的子串就不可能与T相匹配。


          2)S的第i个字符与T的第j个字符相等时,有两种匹配的方式:一,若S的i-1字符匹配T的j-1字符,我们可以选择S的i字符与T   的j字符匹配;二,若S的i-1字符子串已经能与T的j字符匹配,放弃S的i字符与T的j字符。

          因此状态转移方程为,dp[i][j]=dp[i-1][j-1]+dp[i-1][j]。

           dp[i-1][j-1]表示S的i-1字符的子序列中匹配T的j-1字符的数目,因为S的第i个字符等于T的第j个字符,此时我们需要让S[i]与T[j]相匹配,所以要取dp[i-1][j-1],因为S的i-1个字符很有可能已经匹配过T[j]了,为了让S[i]匹配T[j],所以取S[i-1]的子序列中与T[j-1]匹配的数目。

            dp[i-1][j]表示放弃S[i]与T[j]的匹配,因为S的i-1个字符的子序列中已经含有T的j-1个字符的子序列了。当然也可能没有。

         3)S的第i个字符T的第j个字符不相等时,此时取S的i-1字符的子序列中与T的j字符匹配的数目了。当然也可能没有呢过匹配的。所以这个情况下,dp[i][j]=dp[i-1][j]。



代码:

class Solution {public:    int numDistinct(string S, string T) {        int lenS = S.length();int lenT = T.length();if (lenS < lenT){return 0;}vector<vector<int> > dp(lenS + 1, vector<int>(lenT + 1, 0));for (int i = 0; i < lenS; i++){dp[i][0] = 1;}for (int i = 1; i <= lenS; i++){for (int j = 1; j <= lenT; j++){if (S[i - 1] == T[j - 1]){dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];}else{dp[i][j] = dp[i - 1][j];}}}return dp[lenS][lenT];    }};




0 0
原创粉丝点击