Palindrome Substrings in JavaScript with Time Complexity Analysis


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 start with a naive approach and then move to more optimized solutions.

Naive Solution

The naive solution involves generating all possible substrings of the given string and checking each one to see if it is a palindrome. This approach is not optimal because it has a high time complexity due to the large number of substrings generated and checked.

Optimized Solution

We can optimize the solution using dynamic programming or expanding around the center technique.

Dynamic Programming Approach

In this approach, we use a 2D array to store whether a substring is a palindrome. We fill this table in a bottom-up manner.

Expand Around Center Approach

This approach involves expanding around each character and each pair of characters in the string to find all palindromic substrings. This method is more efficient and has a time complexity of O(n^2).

Algorithm

Expand Around Center Algorithm

1. Initialize a count to 0.

2. For each character in the string, expand around the center for both odd and even length palindromes.

3. Increment the count for each palindrome found.

Code Implementation

// Function to count palindromic substrings
function countPalindromicSubstrings(s) {
    let count = 0;

    // Helper function to expand around the center
    function expandAroundCenter(left, right) {
        while (left >= 0 && right < s.length && s[left] === s[right]) {
            count++;
            left--;
            right++;
        }
    }

    // Iterate over each character and expand around center
    for (let i = 0; i < s.length; i++) {
        // Odd length palindromes
        expandAroundCenter(i, i);
        // Even length palindromes
        expandAroundCenter(i, i + 1);
    }

    return count;
}

// Example usage
const input = "abbcbc";
console.log(countPalindromicSubstrings(input)); // 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. The space complexity is O(1) as we are not using any extra space proportional to the input size.

Edge Cases

Potential edge cases include:

  • Empty string: The output should be 0.
  • String with one character: The output should be 1.
  • String with all identical characters: Each substring is a palindrome.

Testing these edge cases ensures the robustness of the solution.

Testing

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

  • Input: "a" - Output: 1
  • Input: "aa" - Output: 3
  • Input: "abc" - Output: 3
  • Input: "aaa" - Output: 6

Using a testing framework like Jest can help automate and validate these test cases.

Thinking and Problem-Solving Tips

When approaching such problems, it's important to:

  • Break down the problem into smaller parts.
  • Consider both naive and optimized solutions.
  • Analyze the time and space complexity of different approaches.
  • Practice similar problems to improve problem-solving skills.

Conclusion

Understanding and solving the problem of counting palindromic substrings is crucial for various applications in computer science. By exploring different approaches and analyzing their complexities, we can develop efficient solutions. Practice and continuous learning are key to mastering such problems.

Additional Resources

For further reading and practice, consider the following resources: