仲舟の奇妙算法(三)【个人版】

21.不同子序列问题
原题:https://leetcode-cn.com/problems/distinct-subsequences-ii/
问题:求字符串s中不同子序列数目
算法类型:动态规划
时间复杂度:o(n)
空间复杂度:o(n)
算法思路:遇到子序列,首先想到是dp,果然真是dp,求子序列的题模板就是dp[i]=dp[i-1]*2+1,但这题要求不重复子序列,那就有点麻烦了。也就是说每次我需要减去前面重复的子序列,例如当 S = “abab” 时,我们有:
dp[0] = 2,它包括 ("", “a”);
dp[1] = 4,它包括 ("", “a”, “b”, “ab”);
dp[2] = 7,它包括 ("", “a”, “b”, “aa”, “ab”, “ba”, “aba”);
dp[3] = 12,它包括 ("", “a”, “b”, “aa”, “ab”, “ba”, “bb”, “aab”, “aba”, “abb”, “bab”, “abab”)。
当从 dp[2] 转移到 dp[3] 时,我们只会在 dp[2] 中的 (“b”, “aa”, “ab”, “ba”, “aba”) 的末尾增加 b,而忽略掉 ("", “a”),因为它们会得到重复的子序列。我们可以发现,这里的 ("", “a”) 刚好就是 dp[0],也就是上一次增加 b 之前的子序列集合。因此我们就得到了如下的状态转移方程:
dp[k] = 2 * dp[k - 1] - dp[last[S[k]] - 1]
即在计算 dp[k] 时,首先会将 dp[k - 1] 对应的子序列的末尾添加 S[k] 得到额外的 dp[k - 1] 个子序列,并减去重复出现的子序列数目,这个数目即为上一次添加 S[k] 之前的子序列数目 dp[last[S[k]] - 1]。
算法难点:
研究时间:2021.10.10 4h

以下题目解析排队中,敬请期待……
https://leetcode-cn.com/problems/minimum-number-of-work-sessions-to-finish-the-tasks/
https://leetcode-cn.com/problems/minimize-the-difference-between-target-and-chosen-elements/
https://leetcode-cn.com/problems/maximum-genetic-difference-query/
https://leetcode-cn.com/problems/last-day-where-you-can-still-cross/
https://leetcode-cn.com/problems/minimum-total-space-wasted-with-k-resizing-operations/
https://leetcode-cn.com/problems/first-day-where-you-have-been-in-all-the-rooms/
https://leetcode-cn.com/problems/gcd-sort-of-an-array/
https://ac.nowcoder.com/acm/contest/11177/B
https://ac.nowcoder.com/acm/contest/11177/C
https://ac.nowcoder.com/acm/contest/11214/I
https://ac.nowcoder.com/acm/contest/11214/B
https://ac.nowcoder.com/acm/contest/18962/D
https://ac.nowcoder.com/acm/contest/18962/I

仲舟原创,未经允许禁止转载!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值