【LEETCODE】115- Distinct Subsequences [Python]

来源:互联网 发布:淘宝手机货到付款骗局 编辑:程序博客网 时间:2024/05/16 12:58

题目:
https://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 的 0 或者多个字母,来得到和 T 一样的字符串,有多少种方式。

Input & Output:

输入就是两个字符串,S 和 T。
输出是数字,即方式的个数。

Edge & Test Cases:

如果 S为空,T为空,则返回1。
如果 S不为空,T为空,则返回1。
如果 S为空,T不为空,则返回0。
如果 S 和 T 都不为空,则返回方式的个数。

Brainstorming:

最初映入脑海的想法是,从字母的个数上去判断,然后从组合的角度去计算,但是行不通,因为这里涉及到顺序,统计完每个字母的个数后,并不能保证它的顺序。

另外一种方法是递归,参考此文。

这个问题和字符串匹配类的问题相似,乍一看来会觉得无从下手,因为删除可以有很多种方式,比如例子,可以在中间删除任意一个b,但是你要如何很快很省力地知道有多少个b呢,又要如何判断剩余字母呢。

如果冷静下来,试着把这个问题分解一下,想一想有什么内在的联系可以缩小问题的范围。

如果 S=rab,T=ra,那么方式有1种,因为末位字母b不等于a,所以可以看作把b删掉,那结果就等于去掉后的方式有多少种。

如果 S=raa,T=ra,即末位字母a等于a,那么一种可能是,仍然把S的末位a去掉,计算S剩余部分和T的匹配种数,另一种可能是,让S的末位a与T的末位a先匹配,所以可以视为都划掉,然后计算S和T的剩余部分的匹配方式数目。

由这种思路,我们可以采用DP来解决这个问题,因为有两个字符串,所以构造一个二维数组。根据上面分析,数组的每个元素,即递推量dp[i][j]就是T的前i个字符构成的串,在S的前j个字符构成的串中,匹配方式有多少个。

如下图:

这是题里给定例子的dp矩阵,最后返回右下角的数字。

python 代码:

class Solution(object):    def numDistinct(self, s, t):        dp = [[0 for j in range(len(s)+1)] for i in range(len(t)+1) ]        for j in range(len(s)+1):            dp[0][j] = 1        for i in range(len(t)):            for j in range(len(s)):                if t[i]==s[j]:                    dp[i+1][j+1] = dp[i+1][j] + dp[i][j]                else:                    dp[i+1][j+1] = dp[i+1][j]        return dp[len(t)][len(s)]

Debugging:

将 Edge & Test Cases 部分提到的几种情况,代入进去正确。
注意,dp的长宽分别加了1,因为考虑了空的情况。同时,循环角标 i,j 指的是相应位置 S 和 T 的元素,留意和dp矩阵相应位置的关系,不要超出范围。

0 0
原创粉丝点击