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'}
.
分析
要求所有不同回文子序列的数量。我们知道求所有回文子序列的动态规划。只需要在此基础上增加一维的状态。
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; } };