
Longest Palindromic Subsequence
14 April, 2023
2
2
0
Contributors
Problem Statement:-
Given a string s
, find the longest palindromic subsequence's length in s
.
A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
Link: https://leetcode.com/problems/longest-palindromic-subsequence/description/
Problem Explanation with examples:-
Example 1
Input: s = "bbbab"
Output: 4
Explanation: One possible longest palindromic subsequence is "bbbb".
Example 2
Input: s = "cbbd"
Output: 2
Explanation: One possible longest palindromic subsequence is "bb".
Constraints
1 <= s.length <= 1000
s
consists only of lowercase English letters.
Intuition:-
- The longest palindromic subsequence is actually the longest common subsequence of the string and its reverse.
- The longest common subsequence is a classic dynamic programming problem. The recurrence relation goes like this:
- We take two indices, idx1 and idx2, and compare the characters at those indices in the two strings. If they are equal, we add 1 to the result of the function call with idx1 and idx2 decremented by 1. If they are not equal, we take the maximum of the function call with idx1 decremented by 1 and idx2 unchanged, and the function call with idx1 unchanged and idx2 decremented by 1.
- The base case is when either of the indices is less than 0. In that case, we return 0.
- We can memoize the function call using the functools.cache decorator. This will make the function run in O(n^2) time and O(n^2) space.
- For longest palindromic subsequence, we can just call the lcs function with the string and its reverse as the first two arguments, and the length of the string minus 1 as the last two arguments.
Solution:-
- Create a recursive lcs function that takes four arguments: s1, s2, idx1, and idx2.
- If either of the indices is less than 0, return 0.
- If the characters at the indices in the two strings are equal, return 1 plus the result of the function call with idx1 and idx2 decremented by 1.
- Otherwise, return the maximum of the function call with idx1 decremented by 1 and idx2 unchanged, and the function call with idx1 unchanged and idx2 decremented by 1.
- Create a variable n and set it equal to the length of the string.
- Return the result of calling the lcs function with the string and its reverse as the first two arguments, and n minus 1 as the last two arguments.
Code:-
JAVA Solution
class Solution {
public static int lcs_memo(String s1, String s2, int n, int m, int[][] dp){
if(n < 0 || m < 0) return 0;
if(dp[n][m] != -1) return dp[n][m];
if(s1.charAt(n) == s2.charAt(m)) return dp[n][m] = 1 + lcs_memo(s1, s2, n-1, m-1, dp);
else return dp[n][m] = Math.max(lcs_memo(s1, s2, n-1, m, dp), lcs_memo(s1, s2, n, m-1, dp));
}
public int longestPalindromeSubseq(String s) {
String s2 = new StringBuilder(s).reverse().toString();
int n = s.length();
int m = s2.length();
int[][] dp = new int[n][m];
for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) dp[i][j] = -1;
return lcs_memo(s, s2, n-1, m-1, dp);
}
}
Python Solution
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
@cache
def lcs(s1, s2, idx1, idx2):
if idx1<0 or idx2<0:
return 0
if s1[idx1] == s2[idx2]:
return 1 + lcs(s1, s2, idx1-1, idx2-1)
return max(lcs(s1, s2, idx1-1, idx2), lcs(s1, s2, idx1, idx2-1))
return lcs(s, s[::-1], n-1, n-1)
Complexity Analysis:-
TIME:-
The time complexity is O(n^2) because we are memoizing the function call.
SPACE:-
The space complexity is O(n^2) + internal recursion stack space because we are memoizing the function call.
References:-
Connect with me:-
java
python
leetcode
dsa