Palindrome Patterns and Techniques for Coding Interviews
Learn the palindrome pattern for interviews, including expand-around-center, DP, palindrome partitioning, and Manacher’s algorithm.
Why palindrome problems show up so often
Palindrome questions are a favorite in interviews because they reveal how you reason about strings, boundaries, and overlapping subproblems. They look simple at first: a string reads the same forward and backward. But once you move past the definition, the problems get richer fast.
You may be asked to find the longest palindromic substring, count all palindromic substrings, split a string into palindromes with the fewest cuts, or solve palindrome partitioning variants. Each version tests a slightly different skill: brute-force thinking, center expansion, dynamic programming, and sometimes advanced linear-time techniques like Manacher.
The good news is that the same core ideas repeat. If you learn the palindrome pattern once, you can reuse it across many interview problems.
Problem statement
A palindrome is a sequence that reads the same in both directions.
Examples:
racecaris a palindromeabbais a palindromeabcis not
Interview problems usually ask one of these:
- Find the longest palindromic substring
- Count all palindromic substrings
- Determine whether a string can be partitioned into palindromes
- Minimize cuts for palindrome partitioning
- Return all palindrome partitions
These are not separate topics. They are variations on the same theme: identify symmetric structure and avoid recomputing the same work.
Core intuition
The key observation is simple:
A palindrome is determined by its center.
That center can be:
- a single character for odd-length palindromes, like
racecar - the gap between two characters for even-length palindromes, like
abba
Once you know a center, you can expand outward while the characters match.
This leads to the most practical interview technique: expand around center.
Another useful observation:
A string
s[i:j]is a palindrome ifs[i] == s[j]and the inside substrings[i+1:j-1]is also a palindrome.
That recursive structure is why dynamic programming works well.
Approach 1: Expand around center
This is usually the best first solution for longest palindromic substring. It is simple, clean, and efficient enough for most interviews.
For each index, treat it as:
- the center of an odd palindrome
- the left center of an even palindrome
Then expand left and right while characters match.
Example 1: Longest palindromic substring
def longest_palindrome(s: str) -> str:
if not s:
return ""
start = end = 0
def expand(left: int, right: int) -> tuple[int, int]:
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return left + 1, right - 1
for i in range(len(s)):
l1, r1 = expand(i, i) # odd length
l2, r2 = expand(i, i + 1) # even length
if r1 - l1 > end - start:
start, end = l1, r1
if r2 - l2 > end - start:
start, end = l2, r2
return s[start:end + 1]How it works
Take s = "babad".
- Center at
b: expand tob - Center at
a: expand tobab - Center at
b: expand toaba
The answer can be bab or aba.
For an even example like s = "cbbd":
- Center between the two
bs givesbb
Why this is good
- Easy to explain
- Easy to implement
- Usually accepted in interviews unless the input is very large
Approach 2: Dynamic programming
If the problem asks about all substrings, or if you want a more systematic solution, DP is a strong option.
Define:
dp[i][j] = True if s[i:j+1] is a palindrome
Transition:
s[i] == s[j]- and either the substring length is 1 or 2, or the inner substring is also a palindrome
That gives:
dp[i][j] = s[i] == s[j] and (j - i < 2 or dp[i + 1][j - 1])
Example 2: Palindrome partitioning check table
Suppose s = "aab".
We want to know which substrings are palindromes:
aat[0][0]aat[1][1]bat[2][2]aaat[0][1]aabis not
Here is the DP solution:
def all_palindrome_substrings(s: str) -> list[list[bool]]:
n = len(s)
dp = [[False] * n for _ in range(n)]
for length in range(1, n + 1):
for i in range(n - length + 1):
j = i + length - 1
if s[i] == s[j] and (length <= 2 or dp[i + 1][j - 1]):
dp[i][j] = True
return dpExample: minimum cuts for palindrome partitioning
A classic interview problem asks for the minimum number of cuts needed so every piece is a palindrome.
For s = "aab", the answer is 1 because you can split it as aa | b.
We first precompute palindrome substrings, then use DP on the prefix.
def min_cut_palindrome_partition(s: str) -> int:
n = len(s)
if n == 0:
return 0
pal = [[False] * n for _ in range(n)]
for end in range(n):
for start in range(end + 1):
if s[start] == s[end] and (end - start < 2 or pal[start + 1][end - 1]):
pal[start][end] = True
cuts = [0] * n
for end in range(n):
if pal[0][end]:
cuts[end] = 0
else:
cuts[end] = min(cuts[start - 1] + 1 for start in range(1, end + 1) if pal[start][end])
return cuts[-1]How to think about it
- First, mark every palindromic substring
- Then, for each prefix ending at
end, try all palindrome starts - Use the best previous cut count
This is a very common interview pattern: precompute a property on intervals, then use it to optimize the final DP.
Approach 3: Manacher’s algorithm
If the interview problem requires the longest palindromic substring and the interviewer asks for optimal time complexity, Manacher’s algorithm is the advanced solution.
It finds the longest palindromic substring in O(n) time.
The idea is to transform the string so odd and even palindromes become uniform. For example:
abbabecomes^#a#b#b#a#$racecarbecomes^#r#a#c#e#c#a#r#$
Then maintain:
center: current palindrome centerright: right boundary of the known palindromep[i]: radius of palindrome centered ati
You reuse previously computed information by mirroring positions around the center.
Example 3: Manacher’s algorithm in Python
def longest_palindrome_manacher(s: str) -> str:
if not s:
return ""
transformed = "^#" + "#".join(s) + "#$"
n = len(transformed)
p = [0] * n
center = right = 0
for i in range(1, n - 1):
mirror = 2 * center - i
if i < right:
p[i] = min(right - i, p[mirror])
while transformed[i + 1 + p[i]] == transformed[i - 1 - p[i]]:
p[i] += 1
if i + p[i] > right:
center = i
right = i + p[i]
max_len = 0
center_index = 0
for i in range(1, n - 1):
if p[i] > max_len:
max_len = p[i]
center_index = i
start = (center_index - max_len) // 2
return s[start:start + max_len]When to use it
Use Manacher when:
- you need the fastest possible runtime
- the input can be very large
- you want to impress, but only if you can explain it clearly
If you cannot explain the mirror trick cleanly, expand-around-center is usually the better interview choice.
Worked example: longest palindromic substring by center expansion
Let’s trace s = "forgeeksskeegfor".
The longest palindrome is geeksskeeg.
Consider the center between the two s characters:
- expand around
sands - match
kandk - match
eande - match
eande - match
gandg
Eventually the expansion stops because the outer characters no longer match.
This is exactly why center expansion works: once the symmetry breaks, you know that center cannot expand further.
Worked example: palindrome partitioning
For s = "nitin", valid partitions include:
n | i | t | i | nn | iti | nnitin
If the problem asks for all valid partitions, you typically combine backtracking with palindrome checks.
A common optimization is to precompute a palindrome table first, then use it during DFS.
def partition_palindromes(s: str) -> list[list[str]]:
n = len(s)
pal = [[False] * n for _ in range(n)]
for end in range(n):
for start in range(end + 1):
if s[start] == s[end] and (end - start < 2 or pal[start + 1][end - 1]):
pal[start][end] = True
result = []
path = []
def dfs(start: int) -> None:
if start == n:
result.append(path[:])
return
for end in range(start, n):
if pal[start][end]:
path.append(s[start:end + 1])
dfs(end + 1)
path.pop()
dfs(0)
return resultThis pattern is useful because it separates two concerns:
- validate palindromes quickly
- explore partitions recursively
Complexity comparison
| Approach | Best for | Time | Space | Notes |
|---|---|---|---|---|
| Expand around center | Longest palindromic substring | O(n^2) | O(1) | Best default interview solution |
| Dynamic programming | Counting/checking substrings, partitioning | O(n^2) | O(n^2) | Great when you need interval reuse |
| Manacher’s algorithm | Longest palindromic substring at scale | O(n) | O(n) | Fastest, but harder to explain |
| Backtracking + DP table | All palindrome partitions | Exponential output size | O(n^2) + recursion | Output can be very large |
Common interview pitfalls
- Forgetting even-length palindromes
- Off-by-one errors in substring boundaries
- Using DP without defining the state clearly
- Mixing up substring indices and lengths
- Recomputing palindrome checks inside recursion
A good habit is to ask yourself:
- What is the center?
- What is the state?
- Can I reuse a previously solved interval?
Related problems to practice
The palindrome pattern appears in many familiar interview questions:
- Longest Palindromic Substring
- Palindromic Substrings
- Palindrome Partitioning
- Palindrome Partitioning II
- Valid Palindrome
- Shortest Palindrome
- Count Different Palindromic Subsequences
Key takeaways
- A palindrome is defined by symmetry around a center.
- Expand-around-center is the simplest and most useful technique.
- Dynamic programming helps when you need to reuse palindrome interval information.
- Manacher’s algorithm gives linear time for longest palindromic substring.
- For partitioning problems, precompute palindrome ranges before backtracking or DP.
If you want to see the variables update live and trace the expansion step by step, check out codebrew.ai.
Practice these next
- Longest Palindromic Substring
- Palindromic Substrings
- Palindrome Partitioning
- Palindrome Partitioning II
- Shortest Palindrome

