Given a string of digits s
, return the number of palindromic subsequences of s
having length 5. Since the answer may be very large, return it modulo 109 + 7.
Note:
Example 1:
Input: s = "103301"
Output: 2
Explanation:
There are 6 possible subsequences of length 5: "10330","10331","10301","10301","13301","03301".
Two of them (both equal to "10301") are palindromic.
Example 2:
Input: s = "0000000"
Output: 21
Explanation: All 21 subsequences are "00000", which is palindromic.
Example 3:
Input: s = "9999900000"
Output: 2
Explanation: The only two palindromic subsequences are "99999" and "00000".
Constraints:
1 <= s.length <= 10^4
s
consists of digits.A naive approach would involve generating all possible subsequences of length 5 from the given string s
and then checking if each subsequence is a palindrome. If it is, we increment our count. The final count, modulo 109 + 7, would be the answer.
def is_palindrome(s):
return s == s[::-1]
def count_palindromic_subsequences_brute_force(s):
n = len(s)
count = 0
mod = 10**9 + 7
for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
for l in range(k + 1, n):
for m in range(l + 1, n):
subsequence = s[i] + s[j] + s[k] + s[l] + s[m]
if is_palindrome(subsequence):
count = (count + 1) % mod
return count
# Example usage:
s = "103301"
print(count_palindromic_subsequences_brute_force(s))
The brute-force approach iterates through all possible combinations of 5 indices in the string. Therefore, the time complexity is O(n5), where n is the length of the string.
The space complexity is O(1), as we're only using a constant amount of extra space.
To improve the time complexity, we can use dynamic programming. The key idea is to count the palindromic subsequences of length 5 by considering the first and last characters. We can build the solution iteratively. Let dp[i][j]
be the number of palindromic subsequences of length j
that start and end with digit i
(0-9). We'll compute palindromes of length 1, 3, and then 5.
i
, iterate through all digits d
from 0-9. If the digit d
occurs before index i
and after index i
, then we can form a palindrome of length 3 with d
as the first and last digits and the digit at index i
as the middle digit.i
, iterate through all digits d
from 0-9. If the number of palindromic subsequences of length 3 that start and end with digit d
occurs before and after index i
, then we can form a palindrome of length 5.def count_palindromic_subsequences(s):
n = len(s)
mod = 10**9 + 7
ans = 0
for digit in range(10):
digit_str = str(digit)
# Find indices of the digit
indices = [i for i, c in enumerate(s) if c == digit_str]
for i in range(len(indices)):
for j in range(i + 1, len(indices)):
l, r = indices[i], indices[j]
# Count palindromes of the form digit + x + y + x + digit
for mid_digit in range(10):
mid_digit_str = str(mid_digit)
mid_indices = [k for k in range(l + 1, r) if s[k] == mid_digit_str]
for m1 in range(len(mid_indices)):
for m2 in range(m1+1, len(mid_indices)):
ans = (ans + 1) % mod
return ans
# Example usage:
s = "103301"
print(count_palindromic_subsequences(s))
The time complexity is O(n * 100), which simplifies to O(n) because the nested loops go from 0-9. This is a significant improvement over the brute-force approach.
The space complexity is O(1), since we are using a fixed amount of extra space to store counts and indices.