详细题目
题目大致意思就是在主串中找不同子串的数量。思路比较明显是动态规划。
令 d p ( i , j ) dp(i, j) dp(i,j)表示 S [ i : ] S[i: ] S[i:]中 T [ j : ] T[j: ] T[j:]出现的次数(S为主串,T为匹配串)。则递推式有:
d p ( i , j ) = { d p ( i + 1 , j ) , if S[i] == T[j] d p ( i + 1 , j + 1 ) + d p ( i + 1 , j ) , if S[i] != T[j] dp(i,j) = \begin{cases} dp(i + 1, j), & \text{if S[i] == T[j]} \\ dp(i + 1,j + 1) + dp(i + 1, j), & \text{if S[i] != T[j]} \end{cases} dp(i,j)={dp(i+1,j),dp(i+1,j+1)+dp(i+1,j),if S[i] == T[j]if S[i] != T[j]
结束条件: d p ( i , j ) = { 1 , if j >= len(T) 0 , if i >= len(S) dp(i,j) = \begin{cases} 1, & \text{if j >= len(T)} \\ 0, & \text{if i >= len(S)} \end{cases} dp(i,j)={1,0,if j >= len(T)if i >= len(S)
(注意结束条件的顺序)
原问题即dp(0,0),动态规划的实现,笔者用相对容易理解的递归实现(注意记忆化)的,当然也可以用扫描数组的形式去实现。
class Solution:
def numDistinct(self, s: str, t: str) -> int:
global d
d = [[-1 for _ in range(len(t))] for _ in range(len(s))]
def dp(i, j):
if j >= len(t):
return 1
if i >= len(s):
return 0
if d[i][j] != -1:
return d[i][j]
if s[i] == t[j]:
ret = dp(i + 1, j + 1) + dp(i + 1, j)
else:
ret = dp(i + 1, j)
d[i][j] = ret
return ret
return dp(0, 0)
LeetCode上的某些题解非要把动态规划的两种形式分开来写,还说成是分治。啧啧啧