LeetCode 115. 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.

算法分析

我们先对例子分析一下,T能在S中能找到多对不同的子序列,换个角度来想,实际上对于某些重复的序列能进行几次组合。而在例子中 rabbit中的‘bb’要在rabbbit中‘bbb’找出组合数,按照这个思路可以算出C(3,2) = 3 也就是这道题的答案。这种想法其实具有很大局限性,比如在’ABBBAB’中就不能用这个方法找到’AB’不同子序列的个数了。
不过这种分析给我们提供了一个思路,也就是要计算重复出现的字母,用动态规划的思维来想,第一想到的应该是构建一个数组来储存答案,然后通过状态转移方程一直迭代到最后达到答案。
这里我们对简单例子可以手写构建一个数组

      A  B  B  B  A  B
   1  1  1   1  1  1  1
A  0  1  1  1  1   2  2
B  0  0  1  2  3   3  5

答案就是 5
这里解释一下这个数组为什么是这样的:
(首先我们定义数组 ans[t.length()+1][s.length()+1])
对于 第 0行来说,意义是对于T为空集的时候,总有唯一一个解
对于 第 0 列来说,对于S为空集的时候,当T不为空集的时候总是没有解
然后对于其他我们有状态转移方程

ans[i][j] = ans[i][j-1] + (T[i-1]==S[j-1]? ans[i-1][j-1] : 0)

分析一下这个状态方程,对于ans[i][j-1]项应该很容易理解,就是每次加入多S的一个字符,目前的序列数不比不加入的少,这也就是动态规划里面的基本的一项。而当T[i-1]==S[j-1]时,证明该字符重复出现或者第一次出现,那么应该累加上T还没加上该字符时候的序列数。
代码如下:


int numDistinct(string s, string t){
    vector<vector<int> > ans(t.length()+1,vector<int>(s.length()+1));

    for(int i = 0 ;i < s.length()+1; i++)
        ans[0][i] = 1; 

    for(int i = 1 ;i < t.length()+1; i++){
        bool first = false;
        for(int j = i ; j < s.length()+1; j++ ){
            ans[i][j] = ans[i][j-1] + (t[i-1]==s[j-1]?ans[i-1][j-1]:0);
        }
    }

    return ans[t.length()][s.length()];
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值