📅  最后修改于: 2023-12-03 15:37:15.214000             🧑  作者: Mango
给定两个字符串 S 和 T,它们仅由下列字符组成:a, b, c, d, e,其中 T 的长度严格大于 S 的长度。定义 T 的一个子序列为仅从 T 删除若干字符但不改变剩余字符相对顺序得到的序列,例如 ebce 是 abcde 的一个子序列,但 bce 不是。现在请你计算有多少个不同的 S 的子序列在 T 中出现。
输入:
abcd
abcde
输出:
4
对于 T 中的每一个字符,都有两种选择:要么使用这个字符,要么不使用这个字符。我们可以使用 DFS 来进行搜索。
在每一步决策时,我们不仅可以选择使用当前的字符,还可以选择放弃使用当前的字符。
如果当前字符和 S 的当前字符相同,那么我们就可以继续考虑 S 的下一个字符和 T 的下一个字符。
如果当前字符和 S 的当前字符不同,那么我们就只能考虑 T 的下一个字符,看看之后有没有机会找到 S 的子序列。
最终,如果我们找到了 S 的子序列,就可以更新答案并返回。
def count_subsequence(s: str, t: str) -> int:
memo = {}
def dfs(i: int, j: int) -> int:
if i == len(s):
return 1
if (i, j) in memo:
return memo[(i, j)]
count = 0
if j < len(t):
count += dfs(i, j + 1)
if s[i] == t[j]:
count += dfs(i + 1, j + 1)
memo[(i, j)] = count
return count
return dfs(0, 0)
代码中,我们定义了一个 memo
字典来记录已经搜索过的状态,避免重复计算。我们的搜索函数是 dfs(i, j)
,表示在 T 的第 j
个位置之后,是否存在 S 的第 i
个位置之后的子序列。如果存在,我们要返回存在的数量。
首先,我们检查 (i, j)
是否已经在 memo
字典中出现过,如果是,我们就直接返回这个状态所对应的答案。否则,我们要根据当前的字符以及 S 和 T 的状态来决策。
如果 j < len(t),说明 T 还有剩余的字符,我们可以考虑使用当前的字符并移动 T 或者不使用当前的字符移动 T。如果当前的字符和 S 的当前字符相同,我们还可以移动 S。
最后,我们把计算出来的答案存在 memo
字典中并返回。