描述
给出字符串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