Taro Logo

Count Palindromic Subsequences

Medium
20 days ago

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 10<sup>9</sup> + 7.

Note:

  • A string is palindromic if it reads the same forward and backward.
  • A subsequence is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters.

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.
Sample Answer
def count_palindromic_subsequences(s):
    n = len(s)
    mod = 10**9 + 7
    count = 0

    for i in range(n - 4):
        for j in range(i + 1, n - 3):
            for k in range(j + 1, n - 2):
                for l in range(k + 1, n - 1):
                    for m in range(l + 1, n):
                        subsequence = s[i] + s[j] + s[k] + s[l] + s[m]
                        if subsequence == subsequence[::-1]:
                            count = (count + 1) % mod

    return count

# Example Usage
s = "103301"
print(f'Input: s = "{s}"\nOutput: {count_palindromic_subsequences(s)}')

s = "0000000"
print(f'Input: s = "{s}"\nOutput: {count_palindromic_subsequences(s)}')

s = "9999900000"
print(f'Input: s = "{s}"\nOutput: {count_palindromic_subsequences(s)}')

Brute Force Solution

The brute force solution iterates through all possible subsequences of length 5 and checks if each subsequence is a palindrome. If it is, we increment a counter, and in the end return the count modulo 10^9 + 7.

Optimal Solution

While the brute force solution works for small inputs, it's not efficient for larger strings. Dynamic programming or other optimization techniques can be explored to improve the time complexity, but for a fixed length of 5, the gains might not be significant enough to justify the added complexity. Given the constraints, the brute-force method is simple enough.

Big(O) Runtime Analysis

  • Brute Force: O(n^5), where n is the length of the string s. This is because we iterate through all possible combinations of 5 indices in the string.

Big(O) Space Usage Analysis

  • Brute Force: O(1), because we are only using a constant amount of extra space to store the count and the subsequence.

Edge Cases

  1. String Length Less Than 5: If the string's length is less than 5, the function will return 0 since no subsequence of length 5 can be formed.
  2. Empty String: An empty string will also return 0, as its length is less than 5.
  3. String With No Palindromic Subsequences: If the string contains no palindromic subsequences of length 5, the function will correctly return 0.
  4. Very Long String: For very long strings, the O(n^5) time complexity might become an issue, but given the constraint of s.length <= 10^4, it should still execute within a reasonable time.
  5. String With Only One Unique Character: For example, "1111111". In this case, all possible subsequences of length 5 would be palindromes.
  6. Modulo Operation: The modulo operation (% (10**9 + 7)) is used to prevent integer overflow when the count of palindromic subsequences becomes very large.