LintCode-不同的子序列-动态规划

描述

给出字符串S和字符串T,计算S的不同的子序列中T出现的个数。

子序列字符串是原始字符串通过删除一些(或零个)产生的一个新的字符串,并且对剩下的字符的相对位置没有影响。(比如,“ACE”是“ABCDE”的子序列字符串,而“AEC”不是)。

样例

给出S = "rabbbit", T = "rabbit"

返回 3

挑战

Do it in O(n2) time and O(n) memory.

O(n2) memory is also acceptable if you do not know how to optimize memory.

思路

简而言之:
当第i个新添加的变量不等于第j个新添加的变量时,当前状态i的上一个状态i-1是否包含j状态的方案次数;
当第i个新添加的变量等于第j个新添加的变量时,当前状态i的上一个状态i-1是否包含j状态的方案次数还有算上状态i-1是否包含状态j-1的的方案次数。

State:
dp[i][j] 表示 S的前i个字符 含 T的前j个字符 的 方案数

Function:
dp[i][j] =
if S[i - 1] == T[i - 1], dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] // 不用S[i - 1]匹配T[j - 1] + 用S[i - 1]匹配T[j - 1]
if S[i - 1] != T[i - 1], dp[i][j] = dp[i - 1][j] // 不用S[i - 1]匹配T[j - 1]

Initialization:
dp[i][0] = 1
dp[0][j] = 0 (j > 0)

Answer:
dp[n][m]

代码

class Solution:
    """
    @param: : A string
    @param: : A string
    @return: Count the number of distinct subsequences
    """

    def numDistinct(self, S, T):
        # write your code here、
        n = len(S)
        m = len(T)
        dp = [[0 for j in range(m+1)] for i in range(n+1)]
        for i in range(n+1):
            dp[i][0] = 1
        for i in range(1, n+1):
            for j in range(1, m+1):
                if j > i:
                    break
                else:
                    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[n][m]

题目来源

https://www.lintcode.com/problem/distinct-subsequences/description

你可能感兴趣的:(LintCode-不同的子序列-动态规划)