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不同子序列计数问题/