Palindromic Substrings
Every palindrome has a centre: a letter for odd lengths, or the gap between two letters for even lengths. There are 2N − 1 centres. From each one, move L to the left and R to the right while the ends match. Each match is one palindrome. The first mismatch ends this centre, and no table is needed.
A range is a palindrome exactly when every pair from its centre outward matches, and the first mismatch ends the palindromes for that centre.
Problem
You are given a string s. Count its palindromic substrings. A substring is a run of letters that sit next to each other in s, and a palindrome reads the same forwards and backwards.
Each substring is counted by its position. If the letter a appears three times, that gives three single-letter palindromes, even though they are the same letter.
A string s of lowercase letters.
The number of substrings of s that are palindromes.
The palindromes are a, b and c. No two letters side by side are equal, so nothing longer works.
They are a, a, a, aa, aa and aaa. The two aa substrings count separately because they start at different positions.
- • 1 ≤ s.length ≤ 1000
- • s consists of lowercase English letters.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Is one letter by itself a palindrome? How many substrings does a string of length N have in total?
- 2.
To check one substring, which pairs of letters must match? Where do the pairs start and end?
- 3.
If
s[l..r]is a palindrome, what must be true about the part inside it,s[l+1..r-1]? - 4.
Every palindrome has a middle. Can I list every possible middle, including the gaps between two letters?
- 5.
If I count the palindromes around each middle by growing outward, can any palindrome be counted twice?
Brute force approach
Better approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Test each substring by comparing its ends, then the next pair inside | O(N^3) | O(1) |
| Better | isPal[i][j] says whether s[i..j] is a palindrome; each cell reads one cell inside it | O(N^2) | O(N^2) |
| Optimal | From each of the 2N − 1 centres, grow outward while the ends match | O(N^2) | O(1) |
Why does this belong to this pattern?
- “count the palindromic substrings”The answer is a count over every contiguous range, so there are about N² candidates to look at.
- “substring (contiguous)”Each candidate is a range s[i..j]. Only its end pairs need to match.
- “reads the same backward as forward”The rule is about mirrored pairs: s[i] = s[j], and then the inside must be a palindrome too.
This is the anchor of the palindrome sub-pattern. A range is a palindrome when its ends match and the range inside it is a palindrome. The table gives every range a cell for that rule, and centre expansion applies the same rule without storing anything. Longest Palindromic Substring uses the same rule but keeps one answer. This problem counts every palindrome, so every matching step adds one to the total instead of only the longest range being kept.
Don't make this mistake
Odd-length palindromes have a letter in the middle, but even-length ones have a gap in the middle, and only the right loop visits the gaps. On abba the wrong loop counts 4 (a, b, b, a) and misses bb and abba, so it gives 4 instead of 6. On the dry-run aabaa it gives 7 instead of 9.
A centre with a long palindrome holds several palindromes, one for each step outward. On aaa the centre at the middle a gives a and aaa, which is 2, but the wrong version adds 1. The total becomes 5 instead of 6.
aa has nothing inside, so it is a palindrome. But isPal[i+1][i] is never filled, so it reads as false and aa is missed. On aaa the table gives 4 instead of 6, because both aa substrings are missed.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like DP — Strings translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.