zoukankan      html  css  js  c++  java
  • 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_

    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'}.

    Approach #1: DFS + Memeory. [C++][MLE]

    class Solution {
    public:
        int countPalindromicSubsequences(string S) {
            return count(S);
        }
        
    private:
        unordered_map<string, long> memo;
        static constexpr long mod = 1000000007;
        
        int count(const string& s) {
            if (s.empty()) return 0;
            if (s.length() == 1) return 1;
            if (memo[s] > 0) return memo[s];
            int len = s.length();
            long ans = 0;
            if (s[0] == s[len-1]) {
                int l = 1, r = len - 2;
                while (l <= r && s[l] != s[0]) l++;
                while (l <= r && s[r] != s[len-1]) r--;
                if (l > r) ans = count(s.substr(1, len-2))*2 + 2;
                else if (l == r) ans = count(s.substr(1, len-2))*2 + 1;
                else ans = count(s.substr(1, len-2))*2 - count(s.substr(l+1, r-l-1));
            } else {
                ans = count(s.substr(0, len-1)) + count(s.substr(1, len-1)) - count(s.substr(1, len-2));  
            }
            
            ans = (ans + mod) % mod;
            // cout << ans << endl;
            
            return memo[s] = ans;
        }
    };
    

      

    Approach #2: Optimization. [C++]

    class Solution {
    public:
        int countPalindromicSubsequences(string S) {
            int len = S.length();
            memo = vector<int>(len*(len+1)+1, 0);
            return count(S, 0, len-1);
        }
        
    private:
        vector<int> memo;
        static constexpr long mod = 1000000007;
        
        int count(const string& S, int s, int e) {
            if (s > e) return 0;
            if (s == e) return 1;
            int key = s * S.length() + e;
            if (memo[key] > 0) return memo[key];
            int len = S.length();
            long ans = 0;
            if (S[s] == S[e]) {
                int l = s+1, r = e-1;
                while (l <= r && S[l] != S[s]) l++;
                while (l <= r && S[r] != S[e]) r--;
                if (l > r) ans = count(S, s+1, e-1)*2 + 2;
                else if (l == r) ans = count(S, s+1, e-1)*2 + 1;
                else ans = count(S, s+1, e-1)*2 - count(S, l+1, r-1);
            } else {
                ans = count(S, s+1, e) + count(S, s, e-1) 
                    - count(S, s+1, e-1);  
            }
            
            return memo[key] = (ans + mod) % mod;
        }
    };
    

      

    Approach #3: DP. [C++]

    class Solution {
        long mod = 1000000007;
        public int countPalindromicSubsequences(String S) {
            int len = S.length();
            long[][] dp = new long[len][len];
            for (int i = 0; i < len; ++i)
                dp[i][i] = 1;
            for (int k = 1; k <= len; ++k) {
                for (int i = 0; i < len-k; ++i) {
                    int j = i + k;
                    if (S.charAt(i) == S.charAt(j)) {
                        dp[i][j] = dp[i+1][j-1] * 2;
                        int l = i + 1;
                        int r = j - 1;
                        while (l <= r && S.charAt(l) != S.charAt(i)) l++;
                        while (l <= r && S.charAt(r) != S.charAt(j)) r--;
                        if (l > r) dp[i][j] += 2;
                        else if (l == r) dp[i][j] += 1;
                        else dp[i][j] -= dp[l+1][r-1];
                    } else
                        dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1];
                    dp[i][j] = (dp[i][j] + mod) % mod;
                }
            }
            return (int)dp[0][len-1];
        }
    }
    

      

    Reference:

    http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-730-count-different-palindromic-subsequences/

    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    常用查看日志的命令
    通过maven profile配置不同开发环境
    java使用shiro小记
    gitlab使用小记
    java使用guava变形数据结构
    php 把驼峰样式的字符串转换成下划线样式的字符串
    tcp粘包和拆包的处理方案
    php和js中,utf-8编码转成base64编码
    yum的用法
    rpm的用法
  • 原文地址:https://www.cnblogs.com/h-hkai/p/10524409.html
Copyright © 2011-2022 走看看