647. Palindromic Substrings¶
Edited by Charles
Medium · Python · Dynamic Programming
Problem
Read the original problem on LeetCode.
The official page contains the problem statement, examples, and constraints.
Explanation, examples & other approaches
Core idea
Given a string s, return the total number of palindromic substrings in s.
A palindrome reads the same forward and backward.
Original study notes follow, including intermediate snippets and earlier attempts.
Idea¶
Given a string s, return the total number of palindromic substrings in s.
A palindrome reads the same forward and backward.
For example:
The palindromic substrings are:
Therefore, the answer is 6.
This problem is different from many previous subsequence DP problems because defining something like
does not give us a clear recurrence.
Instead, we use the key property of a palindrome:
A substring
s[i:j+1]is a palindrome if its two end characters are equal and its inner substrings[i+1:j]is also a palindrome.
This naturally leads to a 2D DP solution.
Dynamic Programming¶
State Definition¶
Let
denote:
Whether the substring
s[i:j+1]is a palindrome.
The interval is inclusive on both sides:
So:
means s[i:j+1] is a palindromic substring.
Initialization¶
Initially, set every state to False.
We should not assume any substring is a palindrome before checking it.
State Transition¶
There are two main cases.
Case 1: s[i] != s[j]¶
If the two end characters are different, the substring cannot be a palindrome.
Therefore:
Since the DP table is initialized to False, no update is needed.
Case 2: s[i] == s[j]¶
If the two end characters are equal, there are three situations.
Situation 1: Single Character¶
If
then the substring contains only one character.
Every single character is a palindrome.
For example:
Situation 2: Two Characters¶
If
and
then the substring is also a palindrome.
For example:
Situation 3: Length Greater Than 2¶
If
and the two end characters are equal, then we only need to check whether the inner substring is a palindrome.
That is:
So:
when
Combined Transition¶
Whenever dp[i][j] becomes True, we have found one palindromic substring, so increment the result.
Why Is j - i <= 1 a Special Case?¶
Consider:
The substring has length 1, so it is automatically a palindrome.
Now consider:
The substring has length 2.
If:
then it is also automatically a palindrome.
For these cases, there is no meaningful inner substring s[i+1:j] to check.
Therefore:
is handled directly.
Traversal Order¶
This is the most important part of this DP solution.
For longer substrings, we use:
to calculate:
So before computing dp[i][j], the state
must already be known.
Notice that dp[i + 1][j - 1] lies below and to the left of dp[i][j] in the DP table.
Therefore, i must be traversed from bottom to top:
For each i, j moves from left to right:
Traversal order:
This guarantees that dp[i + 1][j - 1] has already been computed.
Example¶
The DP table corresponds to substrings s[i:j+1].
i = 2¶
Single character:
Count:
i = 1¶
For:
we get:
For:
since:
and the length is 2:
Now:
i = 0¶
For:
For:
For:
the end characters are equal:
and the inner substring:
is a palindrome because:
Therefore:
Final result:
Complexity Analysis¶
Time Complexity
We examine every possible substring interval [i, j].
Space Complexity
A 2D DP table is used.
Summary¶
State Definition
Initialization
State Transition
Whenever:
increment the palindrome count.
Traversal Order
Final Answer
Common Mistakes¶
-
Do not define the DP state only using one index.
The palindrome property depends on both ends of a substring, so a 2D state is much more natural:
- Do not forget the special cases:
These represent substrings of length 1 or 2.
- When the substring length is greater than
2, checking only
is not enough.
You must also check:
- The traversal order is crucial.
Since:
depends on:
i must be traversed from right to left.
- A substring must be continuous.
This problem counts palindromic substrings, not palindromic subsequences.
Study record
| Field | Value |
|---|---|
| Attempts | 1 |
| Mastery | ❚ |
| The Latest Attempt | August 12, 2026 |
Python solution¶
class Solution:
def countSubstrings(self, s: str) -> int:
l = len(s)
dp = [[False] * l for _ in range(l)]
res = 0
for i in range(l - 1, -1, -1):
for j in range(i, l):
if s[i] == s[j]:
if j - i <= 1:
res += 1
dp[i][j] = True
elif dp[i + 1][j - 1]:
res += 1
dp[i][j] = True
return res
Back to Day 40 Dynamic Programming XIII · All Algorithm notes