0115 Distinct Subsequences#
Problem#
Given two strings s
and t
, return the number of distinct
subsequences of s
which equals t
.
The test cases are generated so that the answer fits on a 32-bit
signed integer.
Examples#
Example 1: Input: s = “rabbbit”, t = “rabbit” Output: 3 Explanation: As shown below, there are 3 ways you can generate “rabbit” from s. rabbbit rabbbit rabbbit
Example 2:
Input: s = “babgbag”, t = “bag” Output: 5 Explanation: As shown below, there are 5 ways you can generate “bag” from s. babgbag babgbag babgbag babgbag babgbag
### Constraint
```text
1 <= s.length, t.length <= 1000
s and t consist of English letters.
Analysis#
This could be a permutation/arrangement problem.
How many ways to make s
(balls) into t
(baskets)?
Solution#
This is a complete problem, which can be solved by:
Backtracking
Dynamic Programming
dp[i,j]
: the number of ways to generatet[j:]
froms[i:]
state
: i, jchoices
:state transition
:if
s[i] != t[j]
: the first character is the not sameonly one choice, which is we cannot put
s[i]
in the bagdp[i,j] = dp[i+1, j]
if
s[i] == t[j]
:there are two choices: put
s[i]
in the bag, or notdp[i,j] = dp[i+1,j+1] + dp[i+1, j]
base case
:j=len(t)
, wheret[j:]
is empty. this always one way, which isnot do anything
.s
shorter thant
: return 0
# DP Function
def distinctSubsequences(s,t):
# dp(i,j) return the number of distinct subsequences of t[j:] in s[i:]
def dp(i, j):
# base case 1
if j == len(t):
return 1
# base case 2
if len(s[i:]) < len(t[j:]):
return 0
# if the current characters do not match
if s[i] != t[j]:
return dp(i+1, j)
else:
return dp(i+1, j+1) + dp(i+1,j)
return dp(0,0)
# test case
# 3
s = "rabbbit"
t = "rabbit"
print(distinctSubsequences(s,t))
# 5
s = "babgbag"
t = "bag"
print(distinctSubsequences(s,t))
3
5
# DP Function with memo
def distinctSubsequences(s,t):
memo = {}
# dp(i,j) return the number of distinct subsequences of t[j:] in s[i:]
def dp(i, j):
# base case 1
if j == len(t):
return 1
# base case 2
if len(s[i:]) < len(t[j:]):
return 0
if (i,j) in memo:
return memo[(i,j)]
# if the current characters do not match
if s[i] != t[j]:
memo[(i, j)] = dp(i+1, j)
else:
memo[(i,j)] = dp(i+1, j+1) + dp(i+1,j)
return memo[(i,j)]
return dp(0,0)
# test case
# 3
s = "rabbbit"
t = "rabbit"
print(distinctSubsequences(s,t))
# 5
s = "babgbag"
t = "bag"
print(distinctSubsequences(s,t))
3
5
# DP table
def distinctSubsequences(s,t):
m, n = len(s), len(t)
dp = [[0] * (n+1) for _ in range(m+1)]
# base case
for i in range(m+1):
dp[i][n] = 1
for j in range(n):
dp[m][j] = 0
for i in range(m-1,-1,-1):
for j in range(n-1, -1, -1):
if s[i] != t[j]:
dp[i][j] = dp[i+1][j]
else:
dp[i][j] = dp[i+1][j+1] + dp[i+1][j]
return dp[0][0]
# test case
# 3
s = "rabbbit"
t = "rabbit"
print(distinctSubsequences(s,t))
# 5
s = "babgbag"
t = "bag"
print(distinctSubsequences(s,t))
3
5