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.
Input: s ="abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba"Output: 104860361Explanation: There are 3104860382 different non-empty palindromic subsequences, which is104860361 modulo 10^9+7.
The problem asks for the count of distinct palindromic subsequences. Since subsequences can overlap and repeat, we need to avoid double-counting. By using DP with memoization, we can efficiently count unique palindromic subsequences in all substrings, leveraging overlapping subproblems.
classSolution {
public:int countPalindromicSubsequences(std::string s) {
constint mod =1e9+7, n = s.size();
std::vector<std::vector<int>> memo(n, std::vector<int>(n, -1));
std::function<int(int, int)> dp = [&](int l, int r) ->int {
if (l > r) return0;
if (memo[l][r] !=-1) return memo[l][r];
int ans =0;
for (char ch ='a'; ch <='d'; ++ch) {
int i = l, j = r;
while (i <= r && s[i] != ch) ++i;
while (j >= l && s[j] != ch) --j;
if (i > j) continue;
if (i == j) ans = (ans +1) % mod;
else ans = (ans +2+ dp(i +1, j -1)) % mod;
}
return memo[l][r] = ans;
};
returndp(0, n -1);
}
};
classSolution {
funcountPalindromicSubsequences(s: String): Int {
val mod = 1_000_000_007
val n = s.length
val memo = Array(n) { IntArray(n) { -1 } }
fundp(l: Int, r: Int): Int {
if (l > r) return0if (memo[l][r] != -1) return memo[l][r]
var ans = 0for (ch in'a'..'d') {
var i = l
var j = r
while (i <= r && s[i] != ch) i++while (j >= l && s[j] != ch) j--if (i > j) continueif (i == j) ans = (ans + 1) % mod
else ans = (ans + 2 + dp(i + 1, j - 1)) % mod
}
memo[l][r] = ans
return ans
}
return dp(0, n - 1)
}
}
classSolution:
defcountPalindromicSubsequences(self, s: str) -> int:
mod: int =10**9+7 n: int = len(s)
memo: list[list[int]] = [[-1] * n for _ in range(n)]
defdp(l: int, r: int) -> int:
if l > r:
return0if memo[l][r] !=-1:
return memo[l][r]
ans: int =0for ch in'abcd':
i, j = l, r
while i <= r and s[i] != ch:
i +=1while j >= l and s[j] != ch:
j -=1if i > j:
continueif i == j:
ans = (ans +1) % mod
else:
ans = (ans +2+ dp(i +1, j -1)) % mod
memo[l][r] = ans
return ans
return dp(0, n -1)
Intuition:
Instead of solving subproblems recursively, we can fill a DP table iteratively for all substrings. For each substring, we count palindromic subsequences by considering the contribution of each character and using previously computed results for smaller substrings.
Approach:
Let dp[i][j] be the number of different palindromic subsequences in s[i..j].
Initialize dp[i][i] = 1 for all i (single characters are palindromic).
For substrings of increasing length (len from 2 to n):
For each substring s[i..j]:
For each character ch in 'a'..'d':
Find the first (l) and last (r) occurrence of ch in s[i..j].
If l > r, skip.
If l == r, add 1 (single character).
If l < r, add 2 (for ch and ch...ch) plus dp[l+1][r-1] (palindromes inside).
classSolution {
public:int countPalindromicSubsequences(std::string s) {
int n = s.size(), mod =1e9+7;
std::vector<std::vector<int>> dp(n, std::vector<int>(n, 0));
for (int i =0; i < n; ++i) dp[i][i] =1;
for (int len =2; len <= n; ++len) {
for (int i =0; i + len -1< n; ++i) {
int j = i + len -1, ans =0;
for (char ch ='a'; ch <='d'; ++ch) {
int l = i, r = j;
while (l <= j && s[l] != ch) ++l;
while (r >= i && s[r] != ch) --r;
if (l > r) continue;
if (l == r) ans = (ans +1) % mod;
else ans = (ans +2+ dp[l +1][r -1]) % mod;
}
dp[i][j] = ans;
}
}
return dp[0][n -1];
}
};
classSolution {
publicintcountPalindromicSubsequences(String s) {
int n = s.length(), mod = 1000000007;
int[][] dp =newint[n][n];
for (int i = 0; i < n; i++) dp[i][i]= 1;
for (int len = 2; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1, ans = 0;
for (char ch ='a'; ch <='d'; ch++) {
int l = i, r = j;
while (l <= j && s.charAt(l) != ch) l++;
while (r >= i && s.charAt(r) != ch) r--;
if (l > r) continue;
if (l == r) ans = (ans + 1) % mod;
else ans = (ans + 2 + dp[l + 1][r - 1]) % mod;
}
dp[i][j]= ans;
}
}
return dp[0][n - 1];
}
}
classSolution {
funcountPalindromicSubsequences(s: String): Int {
val n = s.length
val mod = 1_000_000_007
val dp = Array(n) { IntArray(n) }
for (i in0 until n) dp[i][i] = 1for (len in2..n) {
for (i in0..n - len) {
val j = i + len - 1var ans = 0for (ch in'a'..'d') {
var l = i
var r = j
while (l <= j && s[l] != ch) l++while (r >= i && s[r] != ch) r--if (l > r) continueif (l == r) ans = (ans + 1) % mod
else ans = (ans + 2 + dp[l + 1][r - 1]) % mod
}
dp[i][j] = ans
}
}
return dp[0][n - 1]
}
}
classSolution:
defcountPalindromicSubsequences(self, s: str) -> int:
n: int = len(s)
mod: int =10**9+7 dp: list[list[int]] = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] =1for length in range(2, n +1):
for i in range(n - length +1):
j: int = i + length -1 ans: int =0for ch in'abcd':
l, r = i, j
while l <= j and s[l] != ch:
l +=1while r >= i and s[r] != ch:
r -=1if l > r:
continueif l == r:
ans = (ans +1) % mod
else:
inner = dp[l +1][r -1] if l +1<= r -1else0 ans = (ans +2+ inner) % mod
dp[i][j] = ans
return dp[0][n -1]
impl Solution {
pubfncount_palindromic_subsequences(s: String) -> i32 {
constMOD: i32=1_000_000_007;
let n = s.len();
let s = s.as_bytes();
letmut dp =vec![vec![0; n]; n];
for i in0..n {
dp[i][i] =1;
}
for len in2..=n {
for i in0..=n - len {
let j = i + len -1;
letmut ans =0;
for&ch inb"abcd" {
letmut l = i;
letmut r = j;
while l <= j && s[l] != ch { l +=1; }
while r >= i && s[r] != ch {
if r ==0 { break; }
r -=1;
}
if l > r { continue; }
if l == r {
ans = (ans +1) %MOD;
} else {
let inner =if l +1<= r.saturating_sub(1) {
dp[l +1][r -1]
} else { 0 };
ans = (ans +2+ inner) %MOD;
}
}
dp[i][j] = ans;
}
}
dp[0][n -1]
}
}