Given a string s
, return the number of palindromic substrings in it.
A string is a palindrome when it reads the same backward as forward.
A substring is a contiguous sequence of characters within the string.
Example 1:
Input: s = "abc" Output: 3 Explanation: Three palindromic strings: "a", "b", "c".
Example 2:
Input: s = "aaa" Output: 6 Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
Constraints:
1 <= s.length <= 1000
s
consists of lowercase English letters.This problem asks to find the number of palindromic substrings within a given string. Two efficient solutions are presented: one using a simple two-pointer approach and the other employing Manacher's algorithm.
This solution iterates through all possible centers of palindromes (both single characters and spaces between characters). For each center, it expands outwards using two pointers, counting palindromes.
Approach:
Iteration: The outer loop iterates 2n - 1
times, where n
is the string length. This covers all possible centers: each character as a center and each space between characters as a center. k
represents the index of the center.
Two Pointers: i
and j
are two pointers initialized symmetrically around the center.
Palindrome Check: The while
loop continues as long as i
and j
are within the string bounds and the characters at i
and j
are equal. If they are equal, it indicates a palindrome centered at k
, so the counter ans
is incremented.
Expansion: i
is decremented and j
is incremented to expand outwards.
Return: Finally, the function returns the total count ans
.
Time Complexity: O(n^2) - The nested while loops iterate at most n times in the worst case (all characters are the same) for each of the 2n-1 possible centers.
Space Complexity: O(1) - Constant extra space is used.
Manacher's algorithm is a linear time algorithm for finding the longest palindromic substring. This solution adapts it to count all palindromic substrings.
Approach:
Preprocessing: The input string s
is transformed into t
by inserting '#' between each character and adding '^' and '$' at the beginning and end. This ensures that palindromes centered at characters and spaces between characters are treated uniformly.
p
Array: An array p
is created to store the length of the palindrome centered at each position in t
.
Iteration: The loop iterates through t
(excluding the first and last characters).
p[i]
Calculation: The value p[i]
is calculated using the following logic:
i
is within the current rightmost palindrome (maxRight
), p[i]
is determined using the mirror position (2 * pos - i
).Palindrome Expansion: The while
loop expands the palindrome centered at i
as long as the characters match.
Updating maxRight
and pos
: If a longer palindrome is found, maxRight
and pos
are updated.
Counting Palindromes: ans
is incremented by p[i] // 2
because p[i]
includes the '#' characters.
Return: The function returns the total count of palindromic substrings ans
.
Time Complexity: O(n) - The algorithm iterates through the transformed string t
once.
Space Complexity: O(n) - The p
array uses linear space.
Code Examples (Python):
Solution 1 (Two Pointers):
class Solution:
def countSubstrings(self, s: str) -> int:
ans, n = 0, len(s)
for k in range(n * 2 - 1):
i, j = k // 2, (k + 1) // 2
while ~i and j < n and s[i] == s[j]:
ans += 1
i, j = i - 1, j + 1
return ans
Solution 2 (Manacher's Algorithm):
class Solution:
def countSubstrings(self, s: str) -> int:
t = '^#' + '#'.join(s) + '#$'
n = len(t)
p = [0 for _ in range(n)]
pos, maxRight = 0, 0
ans = 0
for i in range(1, n - 1):
p[i] = min(maxRight - i, p[2 * pos - i]) if maxRight > i else 1
while t[i - p[i]] == t[i + p[i]]:
p[i] += 1
if i + p[i] > maxRight:
maxRight = i + p[i]
pos = i
ans += p[i] // 2
return ans
Manacher's algorithm, despite the added complexity in implementation, offers a significant performance advantage for larger input strings due to its linear time complexity. The two-pointer approach is simpler to understand and implement, but less efficient for large inputs. Choose the solution that best suits your needs based on the expected input size and your priorities (simplicity vs. performance).