Palindrome Substrings in Python with O(n^2) Time Complexity


Given a string, count the number of palindromic contiguous substrings in the string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Example:

Input:  "abbcbc"

Output: 9

Explanation: ["a", "b", "b", "c", "b", "c", "bb", "bcb", "cbc"]

Understanding the Problem

The core challenge of this problem is to identify all substrings of a given string that are palindromic. A palindrome is a string that reads the same forward and backward. The significance of this problem lies in its applications in text processing, DNA sequence analysis, and other fields where pattern recognition is crucial.

Potential pitfalls include missing substrings that are palindromic or counting the same substring multiple times. It's important to ensure that each unique palindromic substring is counted correctly.

Approach

To solve this problem, we can use a dynamic programming approach or expand around the center technique. Let's discuss both:

Naive Solution

A naive solution would involve generating all possible substrings and checking each one for being a palindrome. This approach is not optimal due to its high time complexity of O(n^3).

Optimized Solution: Expand Around Center

A more efficient approach is to expand around the center. For each character in the string, we consider it as the center of a potential palindrome and expand outwards to check for palindromic substrings. This approach has a time complexity of O(n^2).

Algorithm

Here is a step-by-step breakdown of the expand around center algorithm:

  1. Initialize a count to zero.
  2. Iterate over each character in the string, treating it as the center of a palindrome.
  3. For each center, expand outwards while the characters on both sides are equal.
  4. Count each valid palindrome found during the expansion.

Code Implementation

def count_palindromic_substrings(s):
    # Function to count palindromes centered at left and right
    def expand_around_center(s, left, right):
        count = 0
        while left >= 0 and right < len(s) and s[left] == s[right]:
            count += 1
            left -= 1
            right += 1
        return count

    total_count = 0
    for i in range(len(s)):
        # Odd length palindromes (single character center)
        total_count += expand_around_center(s, i, i)
        # Even length palindromes (two character center)
        total_count += expand_around_center(s, i, i + 1)

    return total_count

# Example usage
input_string = "abbcbc"
print(count_palindromic_substrings(input_string))  # Output: 9

Complexity Analysis

The time complexity of the expand around center approach is O(n^2), where n is the length of the string. This is because we are expanding around each character and each pair of characters, and the expansion itself takes linear time in the worst case.

The space complexity is O(1) as we are using a constant amount of extra space.

Edge Cases

Consider the following edge cases:

  • Empty string: The output should be 0.
  • String with one character: The output should be 1.
  • String with all identical characters: The output should be the sum of the first n natural numbers, where n is the length of the string.

Testing

To test the solution comprehensively, consider the following test cases:

assert count_palindromic_substrings("") == 0
assert count_palindromic_substrings("a") == 1
assert count_palindromic_substrings("aa") == 3
assert count_palindromic_substrings("abc") == 3
assert count_palindromic_substrings("aaa") == 6
assert count_palindromic_substrings("abbcbc") == 9

Thinking and Problem-Solving Tips

When approaching such problems, it's important to:

  • Understand the problem requirements and constraints thoroughly.
  • Consider both naive and optimized solutions to understand the trade-offs.
  • Break down the problem into smaller, manageable parts.
  • Practice similar problems to improve problem-solving skills.

Conclusion

In this blog post, we discussed how to count palindromic substrings in a given string using an efficient expand around center approach. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for improving algorithmic thinking and coding skills.

Additional Resources

For further reading and practice, consider the following resources: