LeetCode Solutions
730. Count Different Palindromic Subsequences
Time: $O(n^2)$ Space: $O(n^2)$
class Solution {
public:
int countPalindromicSubsequences(string s) {
constexpr int kMod = 1'000'000'007;
const int n = s.length();
// dp[i][j] := # of different non-empty palindromic subseqs in s[i..j]
vector<vector<int>> dp(n, vector<int>(n));
for (int i = 0; i < n; ++i)
dp[i][i] = 1;
for (int d = 1; d < n; ++d)
for (int i = 0; i + d < n; ++i) {
const int j = i + d;
if (s[i] == s[j]) {
int lo = i + 1;
int hi = j - 1;
while (lo <= hi && s[lo] != s[i])
++lo;
while (lo <= hi && s[hi] != s[i])
--hi;
if (lo > hi)
dp[i][j] = dp[i + 1][j - 1] * 2 + 2;
else if (lo == hi)
dp[i][j] = dp[i + 1][j - 1] * 2 + 1;
else
dp[i][j] = dp[i + 1][j - 1] * 2 - dp[lo + 1][hi - 1];
} else {
dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1];
}
dp[i][j] = (dp[i][j] + kMod) % kMod;
}
return dp[0][n - 1];
}
};
class Solution {
public int countPalindromicSubsequences(String s) {
final int kMod = 1_000_000_007;
final int n = s.length();
// dp[i][j] := # of different non-empty palindromic subseqs in s[i..j]
int[][] dp = new int[n][n];
for (int i = 0; i < n; ++i)
dp[i][i] = 1;
for (int d = 1; d < n; ++d)
for (int i = 0; i + d < n; ++i) {
final int j = i + d;
if (s.charAt(i) == s.charAt(j)) {
int lo = i + 1;
int hi = j - 1;
while (lo <= hi && s.charAt(lo) != s.charAt(i))
++lo;
while (lo <= hi && s.charAt(hi) != s.charAt(i))
--hi;
if (lo > hi)
dp[i][j] = dp[i + 1][j - 1] * 2 + 2;
else if (lo == hi)
dp[i][j] = dp[i + 1][j - 1] * 2 + 1;
else
dp[i][j] = dp[i + 1][j - 1] * 2 - dp[lo + 1][hi - 1];
} else {
dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1];
}
dp[i][j] = (int) ((dp[i][j] + kMod) % kMod);
}
return dp[0][n - 1];
}
}
class Solution:
def countPalindromicSubsequences(self, s: str) -> int:
def count(l: int, r: int) -> int:
if l > r:
return 0
if l == r:
return 1
key = l * len(s) + r
if key in memo:
return memo[key]
if s[l] == s[r]:
lo = l + 1
hi = r - 1
while lo <= hi and s[lo] != s[l]:
lo += 1
while lo <= hi and s[hi] != s[l]:
hi -= 1
if lo > hi:
ans = count(l + 1, r - 1) * 2 + 2
elif lo == hi:
ans = count(l + 1, r - 1) * 2 + 1
else:
ans = count(l + 1, r - 1) * 2 - count(lo + 1, hi - 1)
else:
ans = count(l, r - 1) + count(l + 1, r) - count(l + 1, r - 1)
memo[key] = (ans + kMod) % kMod
return memo[key]
kMod = 1_000_000_007
memo = {}
return count(0, len(s) - 1)