LCR 097. 不同的子序列
大约 2 分钟
---
LCR 097. 不同的子序列
- 标签:字符串、动态规划
- 难度:困难
题目链接
题目大意
给定两个字符串 s 和 t。
要求:计算在 s 的子序列中 t 出现的个数。
解题思路
动态规划求解。
定义状态 dp[i][j]表示为:以 i - 1 为结尾的 s 子序列中出现以 j - 1 为结尾的 t 的个数。
则状态转移方程为:
- 如果
s[i - 1] == t[j - 1],则:dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]。即dp[i][j]来源于两部分:- 使用
s[i - 1]匹配t[j - 1],则dp[i][j]取源于以i - 2为结尾的s子序列中出现以j - 2为结尾的t的个数,即dp[i - 1][j - 1]。 - 不使用
s[i - 1]匹配t[j - 1],则dp[i][j]取源于以i - 2为结尾的s子序列中出现以j - 1为结尾的t的个数,即dp[i - 1][j]。
- 使用
- 如果
s[i - 1] != t[j - 1],那么肯定不能用s[i - 1]匹配t[j - 1],则dp[i][j]取源于dp[i - 1][j]。
下面来看看初始化:
dp[i][0]表示以i - 1为结尾的s子序列中出现空字符串的个数。把s中的元素全删除,出现空字符串的个数就是1,则dp[i][0] = 1。dp[0][j]表示空字符串中出现以j - 1结尾的t的个数,空字符串无论怎么变都不会变成t,则dp[0][j] = 0dp[0][0]表示空字符串中出现空字符串的个数,这个应该是1,即dp[0][0] = 1。
然后递推求解,最后输出 dp[size_s][size_t]。
代码
class Solution:
def numDistinct(self, s: str, t: str) -> int:
size_s = len(s)
size_t = len(t)
dp = [[0 for _ in range(size_t + 1)] for _ in range(size_s + 1)]
for i in range(size_s):
dp[i][0] = 1
for i in range(1, size_s + 1):
for j in range(1, size_t + 1):
if s[i - 1] == t[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
else:
dp[i][j] = dp[i - 1][j]
return dp[size_s][size_t]