• LN : leetcode 730 Count Different Palindromic Subsequences


    lc 730 Count Different Palindromic Subsequences


    730 Count Different Palindromic Subsequences

    Given a string S, find the number of different non-empty palindromic subsequences in S, and return that number modulo 10^9 + 7.

    A subsequence of a string S is obtained by deleting 0 or more characters from S.

    A sequence is palindromic if it is equal to the sequence reversed.

    Two sequences A_1, A_2, ... and B_1, B_2, ... are different if there is some i for which A_i != B_i.

    Example 1:

    Input: 
    S = 'bccb'
    Output: 6
    Explanation: 
    The 6 different non-empty palindromic subsequences are 'b', 'c', 'bb', 'cc', 'bcb', 'bccb'.
    Note that 'bcb' is counted only once, even though it occurs twice.
    

    Example 2:

    Input: 
    S = 'abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba'
    Output: 104860361
    Explanation: 
    There are 3104860382 different non-empty palindromic subsequences, which is 104860361 modulo 10^9 + 7.
    

    Note:

    The length of S will be in the range [1, 1000].
    Each character S[i] will be in the set {'a', 'b', 'c', 'd'}.

    带记忆数组 Accepted

    虽然题目只要求四个字母,但我们扩展普遍性,这里就做二十六个字母的。带记忆数组和动态规划的本质是差不多的。带记忆数组memo的递归解法,这种解法的思路是一层一层剥洋葱,比如"bccb",按照字母来剥,先剥字母b,确定最外层"b _ _ b",这会产生两个回文子序列"b"和"bb",然后递归进中间的部分,把中间的回文子序列个数算出来加到结果res中,然后开始剥字母c,找到最外层"cc",此时会产生两个回文子序列"c"和"cc",然后由于中间没有字符串了,所以递归返回0,按照这种方法就可以算出所有的回文子序列了。

    class Solution {
    public:
        int countPalindromicSubsequences(string S) {
            int len = S.size();
            vector<vector<int>> dp(len+1, vector<int>(len+1, 0));
            vector<vector<int>> ch(26, vector<int>());
            for (int i = 0; i < len; i++) {
                ch[S[i]-'a'].push_back(i);
            }
            return calc(S, ch, dp, 0, len);
        }
        int calc(string S, vector<vector<int>>& ch, vector<vector<int>>& dp, int start, int end) {
            if (start >= end) return 0;
            if (dp[start][end] > 0) return dp[start][end];
            long ans = 0;
            for (int i = 0; i < 26; i++) {
                if (ch[i].empty()) continue;
                auto new_start = lower_bound(ch[i].begin(), ch[i].end(), start);
                auto new_end = lower_bound(ch[i].begin(), ch[i].end(), end) - 1;
                if (new_start == ch[i].end() || *new_start >= end)  continue;
                ans++;
                if (new_start != new_end)   ans++;
                ans += calc(S, ch, dp, *new_start+1, *new_end);
            }
            dp[start][end] = ans % int(1e9+7);
            return dp[start][end];
        }
    };
    
  • 相关阅读:
    JAVAGUI设计步骤
    JAVA接口基础知识总结
    静态关键字static用法。
    JAVA面向对象的多态性
    java封装的概念
    多线程
    关于集合类间的区别
    JAVA——异常
    java——内部类
    Java——接口
  • 原文地址:https://www.cnblogs.com/renleimlj/p/8058943.html
Copyright © 2020-2023  润新知