516. Longest Palindromic Subsequence¶
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 length of the longest palindromic subsequence.
A subsequence does not need to be contiguous, but the relative order of the selected characters must remain unchanged.
Original study notes follow, including intermediate snippets and earlier attempts.
Idea¶
Given a string s, return the length of the longest palindromic subsequence.
A subsequence does not need to be contiguous, but the relative order of the selected characters must remain unchanged.
For example:
One longest palindromic subsequence is:
Therefore, the answer is 4.
The key observation is that when considering a substring s[i:j+1], the result depends on whether the two boundary characters s[i] and s[j] are equal.
Dynamic Programming¶
State Definition¶
Let
denote:
The length of the longest palindromic subsequence inside the substring
s[i:j+1].
The interval is inclusive on both sides:
So dp[i][j] considers every possible subsequence inside this range.
Initialization¶
When
the substring contains only one character.
A single character is always a palindrome of length 1.
Therefore:
All other states can initially remain 0.
State Transition¶
There are two cases.
Case 1: s[i] == s[j]¶
If the two boundary characters are equal, they can both be added to the longest palindromic subsequence inside the interval:
Therefore:
For example:
Since:
we only need to know the longest palindromic subsequence inside:
and then add the two 'c' characters.
Case 2: s[i] != s[j]¶
If the two boundary characters are different, they cannot both be included as matching ends of the same palindrome.
We consider two possibilities:
- Ignore
s[i] - Ignore
s[j]
If we ignore s[i], the result is:
If we ignore s[j], the result is:
Take the larger value:
Transition Equation¶
Traversal Order¶
The transition depends on:
Therefore, before computing dp[i][j]:
- the next row
i + 1must already be computed; - the value to the left
dp[i][j - 1]must already be computed.
So i must be traversed from bottom to top:
and j should move from left to right:
Traversal order:
Final Answer¶
The state:
represents the longest palindromic subsequence inside the entire string.
Therefore, the final answer is:
Example¶
Initialization:
Compare s[2] and s[3]¶
Therefore:
Compare s[1] and s[2]¶
Therefore:
The palindrome is:
Compare s[1] and s[3]¶
Therefore:
Compare s[0] and s[3]¶
Therefore:
Final answer:
Complexity Analysis¶
Time Complexity
We compute every valid interval [i, j].
Space Complexity
A 2D DP table is used.
Summary¶
State Definition
Initialization
State Transition
Traversal Order
Final Answer
Common Mistakes¶
- Do not confuse palindromic subsequence with palindromic substring.
- When:
both boundary characters can be included:
- When:
do not reset the state to 0.
Instead, discard one boundary and take the better result:
- The traversal order is important because
dp[i][j]depends on states from the next row. Therefore,imust be traversed from right to left. - Every single character is a palindrome of length
1, so the diagonal must be initialized as:
Study record
| Field | Value |
|---|---|
| Attempts | 1 |
| Mastery | ❚ |
| The Latest Attempt | August 12, 2026 |
Python solution¶
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
l = len(s)
dp = [[0] * l for _ in range(l)]
for i in range(l):
dp[i][i] = 1
for i in range(l - 1, -1, -1):
for j in range(i + 1, l):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return dp[0][-1]
Back to Day 40 Dynamic Programming XIII · All Algorithm notes