Longest Palindromic Subsequence

Longest Palindromic Subsequence

Leetcode Daily Challenge (14th April, 2023)

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:-

Did you find this article valuable?

Support Leeting-LCS by becoming a sponsor. Any amount is appreciated!