730. Count Different Palindromic Subsequences

来源:互联网 发布:unity3d 机械仿真 编辑:程序博客网 时间:2024/06/01 07:29

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: 6Explanation: 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: 104860361Explanation: 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'}.

    分析

    要求所有不同回文子序列的数量。我们知道求所有回文子序列的动态规划。只需要在此基础上增加一维的状态。

    dp[x][i][j]表示s[i]=s[j]='a'+x的子问题的答案。

    if s[i]!='a'+x ,则dp[x][i][j]=dp[x][i+1][j]

    if s[j]!='a'+x,则dp[x][i][j]=dp[x][i][j-1]

    if s[i]=s[j]='a'+x,则dp[x][i][j]=2+dp[0][i+1][j-1]+dp[1][i+1][j-1]+dp[2][i+1][j-1]+dp[3][i+1][j-1]

    设n为字符串的长度,那么答案就是dp[0][0][n-1]+dp[1][0][n-1]+dp[2][0][n-1]+dp[3][0][n-1]

    class Solution {public:  int countPalindromicSubsequences(string S) {    int n = S.size();    int mod = 1000000007;    auto dp_ptr = new vector<vector<vector<int>>>(4, vector<vector<int>>(n, vector<int>(n)));    auto& dp = *dp_ptr;    for (int i = n-1; i >= 0; --i) {      for (int j = i; j < n; ++j) {        for (int k = 0; k < 4; ++k) {          char c = 'a' + k;          if (j == i) {            if (S[i] == c) dp[k][i][j] = 1;            else dp[k][i][j] = 0;          } else { // j > i            if (S[i] != c) dp[k][i][j] = dp[k][i+1][j];            else if (S[j] != c) dp[k][i][j] = dp[k][i][j-1];            else { // S[i] == S[j] == c              if (j == i+1) dp[k][i][j] = 2; // "aa" : {"a", "aa"}              else { // length is > 2                dp[k][i][j] = 2;                for (int m = 0; m < 4; ++m) { // count each one within subwindows [i+1][j-1]                  dp[k][i][j] += dp[m][i+1][j-1];                  dp[k][i][j] %= mod;                }              }            }          }        }      }    }    int ans = 0;    for (int k = 0; k < 4; ++k) {      ans += dp[k][0][n-1];      ans %= mod;    }    return ans;  }};