【LeetCode-940】不同的子序列 II

问题

给定一个字符串 S,计算 S 的不同非空子序列的个数。

因为结果可能很大,所以返回答案模 10^9 + 7.

示例

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

解答

class Solution {
public:
    int distinctSubseqII(string S) {
        int kMod = 1e9 + 7, n = S.size();
        vector<int> memo(26, -1), dp(n + 1); // dp[0] = 0即空字符时不存在非空子序列
        for (int i = 1; i <= n; i++) {
            int cur = S[i - 1] - 'a';
            if (memo[cur] < 0) dp[i] = (2 * dp[i - 1] + 1) % kMod;
            else dp[i] = (2 * dp[i - 1] - dp[memo[cur]]) % kMod;
            if (dp[i] < 0) dp[i] += kMod; // 因为减法和取模的原因,可能有负数
            memo[cur] = i - 1;
        }
        return dp[n];
    }
};

重点思路

字符串的动态规划。dp[i]表示当前字符(S[i - 1])前所有可能的非空子序列,memo[i]存储当前字符最后一次出现的角标。当前字符第一次出现时(即memo[cur] < 0),增加的新不重复子序列为所有之前的子序列数量加上自己;当前字符不是第一次出现时,此时memo[cur]表示该字符上一次出现的角标,此时新增的子序列数量为dp[i - 1] - dp[memo[cur]],因为之前已有重复的,所以新增子序列数量不再加上自己。

posted @ 2021-04-06 16:19  tmpUser  阅读(82)  评论(0编辑  收藏  举报