326不同子序列计数问题
题解
问题描述
小 U 有一个字符串 s
,他想计算该字符串的所有不同非空子序列的个数。子序列是通过删除原字符串中的部分字符(也可以不删除),且保持剩余字符的相对顺序形成的新字符串。
你的任务是帮助小 U 计算 s
的不同非空子序列的总数,并返回对 $10^9 + 7$ 取余的结果。
例如:
- 当
s = "abc"
时,所有不同的非空子序列包括"a"
,"b"
,"c"
,"ab"
,"ac"
,"bc"
, 和"abc"
,总数为7
。
解题思路
动态规划状态定义:
- 定义
f[i]
为字符串s
的前i
个字符所能形成的不同非空子序列的数量。字典last
记录每个字符上一次出现的位置。
- 定义
动态规划转移:
- 遍历字符串
s
,对于每一个字符c
在索引i
位置:- 如果
c
是第一次出现,即c
不在last
中:- 则
f[i] = f[i-1] * 2 + 1
。这里f[i-1] * 2
表示在所有前i-1
个子序列基础上,每个子序列可以选择添加或不添加c
,+1
表示包含只有c
这个字符的子序列。
- 则
- 如果
c
之前出现过:- 则
f[i] = f[i-1] * 2 - f[last[c] - 1]
。f[i-1] * 2
同理,但需要减去f[last[c] - 1]
,以消除由上一次出现c
到当前c
之间重复形成的子序列,保证每个子序列唯一。
- 则
- 如果
- 更新
last[c] = i
,记录字符c
的最新出现位置。
- 遍历字符串
代码
1 |
|
时间复杂度
- 该算法的时间复杂度为
O(n)
,其中n
是字符串的长度。 - 空间复杂度为
O(n)
,用于存储动态规划数组f
和字符最后出现位置的哈希表last
。
326不同子序列计数问题
https://kongshuilinhua.github.io/2024/12/31/326不同子序列计数问题/