2484. Count Palindromic Subsequences - Detailed Explanation

Free Coding Questions Catalog
Boost your coding skills with our essential coding questions catalog. Take a step towards a better tech career now!

Problem Statement

Given a string s, return the number of different non-empty palindromic subsequences in s. Since the answer may be very large, return it modulo 10⁹ + 7.

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

Important:

  • Two palindromic subsequences are considered different if they occur in different positions or have different compositions.
  • The string s consists only of the characters 'a', 'b', 'c', and 'd'.

Example Inputs & Outputs

  • Example 1:
    Input: "bccb"
    Output: 6
    Explanation:
    The 6 different palindromic subsequences are:

    • "b"
    • "c"
    • "bb"
    • "cc"
    • "bcb"
    • "bccb"
  • Example 2:
    Input: "abcd"
    Output: 4
    Explanation:
    Each character itself is a palindrome. There are no longer palindromic subsequences since all characters are distinct.

  • Example 3:
    Input: "aaa"
    Output: 3
    Explanation:
    The distinct palindromic subsequences are:

    • "a"
    • "aa"
    • "aaa"

Constraints

  • 1 ≤ s.length ≤ 1000
  • s[i] is either 'a', 'b', 'c', or 'd'.

Hints

  1. Dynamic Programming (DP) on Substrings:
    Think about defining a DP state that represents the count of distinct palindromic subsequences in a substring of s. For example, let dp[i][j] denote the answer for the substring s[i…j].

  2. Handling Duplicate Subsequences:
    When the two ends of a substring are the same (say, s[i] == s[j]), you need to carefully count additional palindromes—taking into account whether there are more of the same character between i and j. You might have to consider three cases:

    • No same character exists between i and j.
    • Exactly one occurrence exists.
    • More than one occurrence exists.
  3. Recurrence Based on End Characters:
    If s[i] != s[j], the answer for s[i…j] can be expressed in terms of dp[i+1][j], dp[i][j-1], and dp[i+1][j-1].

Approaches

1. Brute Force (Not Feasible)

  • Idea: Generate all subsequences and check for palindromes while ensuring uniqueness.
  • Drawback: The total number of subsequences is exponential (2ⁿ), which makes this approach impractical for s.length up to 1000.

2. Optimal Dynamic Programming Approach

Idea:
Use a two-dimensional DP array dp[i][j] that stores the number of distinct palindromic subsequences in the substring s[i…j].
The recurrence is built based on whether s[i] and s[j] are the same:

  • If s[i] != s[j]: [ dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1] ] Here, you add the subsequences from the right and left parts and subtract the overlapping subsequences counted twice.

  • If s[i] == s[j]:
    Let char = s[i] and then find the first occurrence l and the last occurrence r of char in the substring s[i+1…j-1].

    • Case 1: No occurrence of char in s[i+1…j-1]
      [ dp[i][j] = dp[i+1][j-1] \times 2 + 2 ] (The extra “+2” counts the subsequences: the single character and the pair "cc".)

    • Case 2: One occurrence of char in s[i+1…j-1]
      [ dp[i][j] = dp[i+1][j-1] \times 2 + 1 ]

    • Case 3: More than one occurrence of char in s[i+1…j-1]
      [ dp[i][j] = dp[i+1][j-1] \times 2 - dp[l+1][r-1] ] (Subtract the palindromic subsequences that are double-counted between the first and last occurrences.)

  • Base Case:
    For a single character (i.e. when i == j), there is exactly 1 palindromic subsequence: [ dp[i][i] = 1 ]

Modular Arithmetic:
Remember to take results modulo 10⁹ + 7 at each step.

Step-by-Step Walkthrough

Consider the string s = "bccb":

  1. Initialization:
    For all i, set dp[i][i] = 1 since each individual character is a palindrome.

  2. Length 2 Substrings:
    Evaluate all substrings of length 2.

    • For s[0…1] = "bc" (b ≠ c):
      [ dp[0][1] = dp[1][1] + dp[0][0] - dp[1][0] \quad \text{(dp[1][0] is 0 by convention)} = 1 + 1 = 2 ]
    • Similar process for other substrings.
  3. Length 4 Substring ("bccb"):
    For s[0] == s[3] ('b'):

    • Find the first occurrence of 'b' in s[1…2] → not found (only 'c' exists), so this is Case 1.
    • Then,
      [ dp[0][3] = dp[1][2] \times 2 + 2 ]
    • After computing dp[1][2] (which counts palindromic subsequences in "cc"), you derive the final answer.

Note: The detailed values in each dp cell require careful iteration by increasing substring lengths.

Code Implementations

Python Code

Python3
Python3

. . . .

Java Code

Java
Java

. . . .

Complexity Analysis

  • Time Complexity:
    The algorithm uses a nested loop to fill an n x n DP table, leading to a time complexity of O(n²).

  • Space Complexity:
    The DP table requires O(n²) space.

Common Mistakes

  1. Not Using Modulo at Every Step:
    Failing to take modulo 10⁹ + 7 after every arithmetic operation can lead to integer overflow.

  2. Double-Counting Subsequences:
    Without careful handling of cases when s[i] == s[j], it’s easy to count duplicate palindromic subsequences.

  3. Incorrect Base Cases:
    Forgetting that every single character is a palindromic subsequence (i.e. dp[i][i] = 1) leads to errors.

Edge Cases & Alternative Variations

  • Edge Cases:

    • Single Character String:
      The answer should be 1 since there’s only one palindromic subsequence.
    • All Characters Are the Same:
      Special care must be taken to avoid over-counting when many duplicate characters exist.
  • Alternative Variations:

    • Counting All Palindromic Subsequences (Not Necessarily Distinct):
      The approach would be simpler, but here we need to account for uniqueness.
    • Other String Subsequence Counting Problems:
      Variations might involve counting subsequences that satisfy different conditions, such as “Longest Palindromic Subsequence.”
  • Longest Palindromic Subsequence:
    Determine the length of the longest palindromic subsequence in a given string.
  • Palindromic Substrings:
    Count all palindromic substrings in a given string.
  • Distinct Subsequences:
    Count the number of distinct subsequences in a string.
TAGS
leetcode
CONTRIBUTOR
Design Gurus Team
-

GET YOUR FREE

Coding Questions Catalog

Design Gurus Newsletter - Latest from our Blog
Boost your coding skills with our essential coding questions catalog.
Take a step towards a better tech career now!
Explore Answers
Related Courses
Grokking the Coding Interview: Patterns for Coding Questions
Grokking the Coding Interview Patterns in Java, Python, JS, C++, C#, and Go. The most comprehensive course with 476 Lessons.
Grokking Modern AI Fundamentals
Master the fundamentals of AI today to lead the tech revolution of tomorrow.
Grokking Data Structures & Algorithms for Coding Interviews
Unlock Coding Interview Success: Dive Deep into Data Structures and Algorithms.
Image
One-Stop Portal For Tech Interviews.
Copyright © 2025 Design Gurus, LLC. All rights reserved.
;