【2022-10-14每日一题】940. 不同的子序列 II[Hard]

2022-10-14
2分钟阅读时长

2022-10-14每日一题:940. 不同的子序列 II

难度:Hard

标签:字符串 、 动态规划

给定一个字符串 s,计算 s不同非空子序列 的个数。因为结果可能很大,所以返回答案需要对 10^9 + 7 取余

字符串的 子序列 是经由原字符串删除一些(也可能不删除)字符但不改变剩余字符相对位置的一个新字符串。

  • 例如,"ace""abcde" 的一个子序列,但 "aec" 不是。

 

示例 1:

输入:s = "abc"
输出:7
解释:7 个不同的子序列分别是 "a", "b", "c", "ab", "ac", "bc", 以及 "abc"。

示例 2:

输入:s = "aba"
输出:6
解释:6 个不同的子序列分别是 "a", "b", "ab", "ba", "aa" 以及 "aba"。

示例 3:

输入:s = "aaa"
输出:3
解释:3 个不同的子序列分别是 "a", "aa" 以及 "aaa"。

 

提示:

  • 1 <= s.length <= 2000
  • s 仅由小写英文字母组成

 

方法一:动态规划

详细思路过程见官方题解,这里只做个人刷题记录,方便后续查询阅读

const mod int = 1e9+7
func distinctSubseqII(s string) int {
    last := make([]int, 26)
    for i := range last {
        last[i] = -1
    }
    n := len(s)
    f := make([]int, n)
    for i, c := range s {
        f[i] = 1 // 初始化
        for _, j := range last {
            if j != -1 { // 没有出现过 last[j]=−1
                f[i] = (f[i]+f[j]) % mod
            }
        }
        last[c-'a'] = i
    }
    ans := 0
    for _, j := range last {
        if j != -1 {
            ans = (ans + f[j]) % mod
        }
    }
    return ans
}

复杂度分析

  • 时间复杂度:O(n∣Σ∣),其中 n 是字符串 s 的长度,Σ 是字符集,在本题中 ∣Σ∣=26。即为动态规划需要的时间。

  • 空间复杂度:O(n+∣Σ∣)。即为数组 f 和 last 需要的空间。

方法二:优化的动态规划

const mod int = 1e9+7
func distinctSubseqII(s string) int {
    g := make([]int, 26)
    for _, c := range s {
        total := 1
        for _, v := range g {
            total = (total+v) % mod
        }
        g[c-'a'] = total
    }
    ans := 0
    for _, v := range g {
        ans = (ans + v) % mod
    }
	return ans
}

复杂度分析

  • 时间复杂度:O(n∣Σ∣),其中 n 是字符串 s 的长度,Σ 是字符集,在本题中 ∣Σ∣=26。即为动态规划需要的时间。

  • 空间复杂度:O(∣Σ∣)。即为数组 g 和 last 需要的空间。

方法三:继续优化的动态规划

const mod int = 1e9+7
func distinctSubseqII(s string) int {
    ans := 0
    g := make([]int, 26)
    for _, c := range s {
        oi := c - 'a' 
        prev := g[oi]
        g[oi] = (ans + 1) % mod // 更新 g[oi]
        //当前序列的个数 = 之前的 + 新增的 - 重复的
        ans = ((ans+g[oi]-prev)%mod+mod)%mod // 更新 ans,并保证 ans 非负
    }
	return ans
}

复杂度分析

  • 时间复杂度:O(n+∣Σ∣)。其中 n 是字符串 s 的长度,Σ 是字符集,在本题中 ∣Σ∣=26。初始化需要的时间为 O(∣Σ∣),动态规划需要的时间的为 O(n)。

  • 空间复杂度:O(∣Σ∣)。即为数组 g 需要的空间。

LeetCode题库地址