LeetCode 730. Count Different Palindromic Subsequences

Question

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

Analysis

具体思路是，设dp[i,j]表示S[i]到S[j]之间这段字符串中不重复的回文子串的数量。那么在求dp[i,j]的时候，根据S[i]和S[j]是否相同，进行分类讨论。主要思想是用子问题组合解决新问题，同时去掉重复计数的部分。

S[i+1]-S[j-1]中间没有S[i]: dp[i,j] = dp[i+1, j-1] * 2 + 2

S[i+1]-S[j-1]中间有一个S[i]: dp[i,j] = dp[i+1, j-1] * 2 + 1

S[i+1]-S[j-1]中间有两个S[i]，其中第一个S[i]出现在ii位置，最后一个出现在jj位置: dp[i,j] = dp[i+1, j-1] * 2 - dp[ii+1, jj-1]

只要理解了其中的思路，实现起来就非常容易了。

Solution

class Solution {
public:
int countPalindromicSubsequences(string S) {
int n = S.length();
long int mod = 1000000007;
vector<vector<long int>>dp(n, vector<long int>(n, 0));
for(int i = 0; i < n; ++i){
dp[i][i] = 1;
}
for(int len = 1; len < n; ++len){
for(int i = 0; i < n - len; ++i){
int j = i + len;
if(S[i] == S[j]){
int ii = i + 1;
while(S[ii] != S[i])
ii++;
int jj = j - 1;
while(S[jj] != S[j])
jj--;
if(ii == jj)
dp[i][j] = dp[i + 1][j - 1] * 2 + 1;
else if(ii > jj)
dp[i][j] = dp[i + 1][j - 1] * 2 + 2;
else
dp[i][j] = dp[i + 1][j - 1] * 2 - dp[ii + 1][jj - 1];
}
else{
dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1];
}
dp[i][j] = (dp[i][j] + mod) % mod;
}
}
return dp[0][n - 1];
}
};