This problem can be solved using two approaches:
Dynamic Programming Time Complexity: O(n²) Space Complexity: O(n²)
Two-Pointer (Expand Around Center) Time Complexity: O(n²) Space Complexity: O(1)
Approach I: Dynamic Programming
In this approach, we aim to check all substrings of the string. Specifically, we will check substrings of lengths 1, 2, 3, …, up to len(s)
.
We use a 2D array dp
of size n x n
where n
is the length of the string. The rows represent the starting index, and the columns represent the length of the substring. For example, dp[5][7]
represents the substring starting at index 5 with a length of 7.
For dp[i][length]
to be True
, the following conditions need to be satisfied:
- The first and last characters of the substring must be the same (
s[i] == s[i + length]
). - The middle substring (between the first and last characters) must also be a palindrome (
dp[i+1][length-2]
).
Base Cases:
- All single-character substrings are palindromes:
for i in range(len(s)): dp[i][0] = True count[0] += 1 # Check for two-character palindromes: for i in range(len(s) - 1): if s[i] == s[i+1]: dp[i][1] = True count[0] += 1
Explanation of DP Filling
When computing dp[i][length]
, where length
represents the length of the substring we are evaluating, we follow these conditions:
- First Condition: The first and last characters of the substring must be the same. This is checked using:
s[i] == s[i + length]
This condition ensures that the characters at the starting index i and the index i + length are identical.
- Second Condition: The middle substring (the portion of the substring that excludes the first and last characters) must also be a palindrome. This is checked with:
dp[i + 1][length - 2]
Here, i + 1 is the starting index of the middle substring, and length - 2 represents its length. If this condition is True, it indicates that the substring formed by excluding the first and last characters is also a palindrome.
Thus, for dp[i][length] to be True, both conditions must be satisfied. If they are, we can increment our count of palindromic substrings
Base Case Code
The base cases for the DP table are established as follows:
Single-Character Substrings: All single-character substrings are palindromes. This is represented in the DP table by setting
dp[i][0]
toTrue
for all valid indicesi
. We also increment the count of palindromic substrings.def baseCasesForDP(self, dp: list[list[bool]], s: str, count: list[int]) -> None: for i in range(len(s)): dp[i][0] = True count[0] += 1 for i in range(len(s) - 1): if s[i] == s[i+1]: dp[i][1] = True count[0] += 1
DP Initialization
We initialize the dp array and a count list to track the number of palindromes: ```python # Variable initialization rows = len(s) cols = len(s) count = [0] # List to store the count (as integers are immutable in Python)
# DP Initialization
dp = []
for i in range(rows):
t = [False] * cols
dp.append(t)
Filling the DP Table
We then fill the DP table for substrings of length 3 and above:
length = 2
for length in range(2, len(s)):
for i in range(len(s) - length):
if s[i] == s[i + length] and dp[i + 1][length - 2] == True:
dp[i][length] = True
count[0] += 1
## Full Code