题解
动态规划
我们使用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示
S
S
S的前
j
j
j个字符有几种方式构成
T
T
T的前
i
i
i个字符。在
S
S
S和
T
T
T前插入空字符,便于计算。
易知,初始化
d
p
dp
dp数组第一行全为
1
1
1,第一列除首位全为
0
0
0。
d
p
[
0
]
[
j
]
dp[0][j]
dp[0][j]表示
S
S
S的前
j
j
j位可以构成空序列的方法数。
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]表示
T
T
T的前
i
i
i位可以由空字符构成的方法数。
- 初始化 S , T S,T S,T的长度分别为 l e n 1 , l e n 2 len1,len2 len1,len2
- 初始化 d p dp dp为 ( l e n 2 + 1 ) ∗ ( l e n 1 + 1 ) (len2+1)*(len1+1) (len2+1)∗(len1+1)的全零数组,将第一行置为全置为 1 1 1
- 遍历
d
p
dp
dp数组,每一行
i
i
i,遍历区间
[
1
,
l
e
n
2
+
1
)
[1,len2+1)
[1,len2+1):
- 每一列
j
j
j,遍历区间
[
1
,
l
e
n
1
+
1
)
[1,len1+1)
[1,len1+1):
- 若 T [ i − 1 ] = = S [ j − 1 ] ] T[i-1]==S[j-1]] T[i−1]==S[j−1]],此时: d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i ] [ j − 1 ] dp[i][j]=dp[i-1][j-1]+dp[i][j-1] dp[i][j]=dp[i−1][j−1]+dp[i][j−1]。解释:如图中绿色单元格所示, d p [ 1 ] [ 5 ] dp[1][5] dp[1][5],表示序列 T [ 0 ] T[0] T[0]可以由序列 S [ 0 , 1 , 2 , 3 , 4 ] S[0,1,2,3,4] S[0,1,2,3,4]构成的方法数。 T [ 0 ] = = S [ 4 ] T[0]==S[4] T[0]==S[4],此时 d p [ 1 ] [ 5 ] dp[1][5] dp[1][5]等于黄色单元格( d p [ 0 ] [ 4 ] dp[0][4] dp[0][4], d p [ 1 ] [ 4 ] dp[1][4] dp[1][4])之和。 d p [ 0 ] [ 4 ] dp[0][4] dp[0][4]表示空字符可以由 S [ 0 , 1 , 2 , 3 ] S[0,1,2,3] S[0,1,2,3](“babg”)有一种构成方法, d p [ 1 ] [ 4 ] dp[1][4] dp[1][4]表示 T [ 0 ] T[0] T[0](“b”)可以由 S [ 0 , 1 , 2 , 3 ] S[0,1,2,3] S[0,1,2,3](“babg”)有两种构成方法。那么 T [ 0 ] T[0] T[0](“b”)可以由空字符+ S [ 4 ] S[4] S[4]或者"b"不加,所以方法数为二者之和。即 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i ] [ j − 1 ] dp[i][j]=dp[i-1][j-1]+dp[i][j-1] dp[i][j]=dp[i−1][j−1]+dp[i][j−1]
- 否则, d p [ i ] [ j ] = d p [ i ] [ j − 1 ] dp[i][j]=dp[i][j-1] dp[i][j]=dp[i][j−1]。如蓝色单元格所示,因为"a" ! = != !=“b”,所以"ba"由"bab"构成的方式依旧等于由"ba"构成的方法数。
- 每一列
j
j
j,遍历区间
[
1
,
l
e
n
1
+
1
)
[1,len1+1)
[1,len1+1):
- 返回 d p [ − 1 ] [ − 1 ] dp[-1][-1] dp[−1][−1]
复杂度分析
- 时间复杂度: O ( m ∗ n ) O(m*n) O(m∗n), m m m为 T T T的长度, n n n为 S S S的长度。
- 空间复杂度: O ( m ∗ n ) O(m*n) O(m∗n)
Python
class Solution:
def numDistinct(self, s: str, t: str) -> int:
len1=len(s)
len2=len(t)
dp=[[1]*(len1+1)]+[[0]*(len1+1) for _ in range(len2)]
for i in range(1,len2+1):
for j in range(1,len1+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[-1][-1]