问题
给定字符串S和字符串T,在S的子序列中,和T相同的有多少个。
Input: S = "rabbbit", T = "rabbit"
Output: 3
rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
思路
用dp[i][j]表示T[:i]和S[:j]之间的解。
如果T[i-1] != S[j-1],那么dp[i][j] = dp[i][j-1],因为末尾的字符不相等,不可能产生新的子串。
如果T[i-1] == S[j-1],当末尾字符相同时,先考虑S[:j-1]中本身有多少个子序列T[:i],有dp[i][j-1]个这样的序列。
然后考虑S[:j-1]中有多少个前缀子序列T[:i-1],这些子序列配上S[i-1](也是T[i-1])可以形成子序列T[:i],有dp[i-1][j-1]个这样的序列T[:i]。
所以此时dp[i][j] = dp[i][j-1] + dp[i-1][j-1]。
dp矩阵可以优化成数组,这里不多解释了,和之前 486. Predict the Winner 给出的三个gif图是一样的道理。
时间复杂度O(n*m),空间复杂度O(n*m)
代码
class Solution(object):
def numDistinct(self, s, t):
"""
:type s: str
:type t: str
:rtype: int
"""
if(len(t) == 0 or len(s) == 0 or len(t) > len(s)):
return 0
dp = [ [0 for _ in range(len(s)+1)] for _ in range(len(t)+1)]
for j in range(len(s)+1):
dp[0][j]=1
for i in range(1,len(t)+1):
for j in range(i,len(s)+1):
if(t[i-1]==s[j-1]):
dp[i][j]=dp[i-1][j-1]+dp[i][j-1]
else:
dp[i][j]=dp[i][j-1]
return dp[len(t)][len(s)]