蠡口115. Distinct Subsequences

又是要对两个字符串一顿操作,返回T or F,典型的dp。

1、建立dp矩阵,确定状态变量:dp[i][j]表示the number of distinct subsequences of s[0:i] which equals t[0:j],就是s[0:i]与t[0:j]带入函数所得值,初值都设为0;

2、确定边界:当s为空字符时,如果t不为空字符,那么就不能通过对s里字符进行删减得到与t字符串一样的字符串,所以dp[0][j]应该为0 (对任意j>0)。当t为空字符,当且仅当删除s中全部字符才能得到空字符,所以dp[i][0](对任意i,包括0,因为空字符不做任何处理也是空字符);

3、建立转移方程:当我们考虑dp[i][j]时,可能有两种情况:1)s[i-1]≠t[j-1];2)s[i-1]==t[j-1]。下面我们分情况讨论,可借助下图理解:

  1)s[i-1]≠t[j-1]时,要将s[0:i]变成t[0:j],至少要将s[i-1]删除,也就是删除s[k:i] (其中k>0),那么dp[i][j]是不是等于Σdp[k][j]呢?其实dp[i-1][j]已经包括了前面的所有dp[k][j]。回想一下dp矩阵的定义,dp[i-1][j]表示的是s的前i-1个字符能变换得到t的前j个字符的总变换数,那么它就包括了所有k (k>0),s[0:k]变换成t[0:j],再将s[k:i]删除这样的操作。所以dp[i-1][j]就是所有这样的操作数。(真是一顿操作猛如虎啊!)。故dp[i][j]=dp[i-1][j];

  2)s[i-1]==t[j-1],这时候可以删除s[i-1],看dp[i-1][j],也可以保留s[i-1],看dp[i-1][j-1]。这时候需注意类似于dp[i-1][j],dp[i-1][j-1]也包括了所有s[0:k]变换成t[0:(j-1)],再将s[k:(i-1)]删除这样的操作。故dp[i][j]=dp[i-1][j]+dp[i][j-1];

 4、返回值:应该返回dp[lens][lent]: s[0:lens]变换得到t[0:lent]的变换数。

 

class Solution(object):
    def numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        if len(s)<len(t): return(0)
        lens,lent=len(s),len(t)
        #dp[i][j]: the number of distinct subsequences of s[0:i] which equals t[0:j]
        dp=[[0 for j in range(lent+1)] for i in range(lens+1)]
        for i in range(lens+1): dp[i][0]=1
        for i in range(1,lens+1):
            for j in range(1,lent+1):
                dp[i][j]=dp[i-1][j]
                if s[i-1]==t[j-1]: dp[i][j]+=dp[i-1][j-1]
        return(dp[lens][lent])
扫描二维码关注公众号,回复: 7508732 查看本文章

猜你喜欢

转载自www.cnblogs.com/Leisgo/p/11703574.html