Longest Palindromic Subsequence | DP-12 - GeeksforGeeks

25 Apr, 2022
Given a sequence, find the length of the longest palindromic subsequence in it. 
As another example, if the given sequence is “BBABCBCAB”, then the output should be 7 as “BABCBAB” is the longest palindromic subsequence in it. “BBBBB” and “BBCBB” are also palindromic subsequences of the given sequence, but not the longest ones.The naive solution for this problem is to generate all subsequences of the given sequence and find the longest palindromic subsequence. This solution is exponential in terms of time complexity. Let us see how this problem possesses both important properties of a Dynamic Programming (DP) Problem and can efficiently be solved using Dynamic Programming.1) Optimal Substructure: Let X[0..n-1] be the input sequence of length n and L(0, n-1) be the length of the longest palindromic subsequence of X[0..n-1]. If last and first characters of X are same, then L(0, n-1) = L(1, n-2) + 2. Else L(0, n-1) = MAX (L(1, n-1), L(0, n-2)).  
Following is a general recursive solution with all cases handled.  
// Every single character is a palindrome of length 1
L(i, i) = 1 for all indexes i in given sequence

// IF first and last characters are not same
If (X[i] != X[j])  L(i, j) =  max{L(i + 1, j),L(i, j - 1)} 

// If there are only 2 characters and both are same
Else if (j == i + 1) L(i, j) = 2  

// If there are more than two characters, and first and last 
// characters are same
Else L(i, j) =  L(i + 1, j - 1) + 2 
2) Overlapping Subproblems Following is a simple recursive implementation of the LPS problem. The implementation simply follows the recursive structure mentioned above.  
C++
C
Java
Python3
C#
PHP
Javascript
// C++ program of above approach#include<bits/stdc++.h>using namespace std; // A utility function to get max of two integersint max (int x, int y) { return (x > y)? x : y; } // Returns the length of the longest palindromic subsequence in seqint lps(char *seq, int i, int j){// Base Case 1: If there is only 1 characterif (i == j)    return 1; // Base Case 2: If there are only 2// characters and both are sameif (seq[i] == seq[j] && i + 1 == j)    return 2; // If the first and last characters matchif (seq[i] == seq[j])    return lps (seq, i+1, j-1) + 2; // If the first and last characters do not matchreturn max( lps(seq, i, j-1), lps(seq, i+1, j) );} /* Driver program to test above functions */int main(){    char seq[] = "GEEKSFORGEEKS";    int n = strlen(seq);    cout << "The length of the LPS is "         << lps(seq, 0, n-1);    return 0;} // This code is contributed// by Akanksha Rai
// C program of above approach#include<stdio.h>#include<string.h> // A utility function to get max of two integersint max (int x, int y) { return (x > y)? x : y; } // Returns the length of the longest palindromic subsequence in seqint lps(char *seq, int i, int j){   // Base Case 1: If there is only 1 character   if (i == j)     return 1;    // Base Case 2: If there are only 2 characters and both are same   if (seq[i] == seq[j] && i + 1 == j)     return 2;    // If the first and last characters match   if (seq[i] == seq[j])      return lps (seq, i+1, j-1) + 2;    // If the first and last characters do not match   return max( lps(seq, i, j-1), lps(seq, i+1, j) );} /* Driver program to test above functions */int main(){    char seq[] = "GEEKSFORGEEKS";    int n = strlen(seq);    printf ("The length of the LPS is %d", lps(seq, 0, n-1));    getchar();    return 0;}
//Java program of above approach class GFG {     // A utility function to get max of two integers    static int max(int x, int y) {        return (x > y) ? x : y;    }    // Returns the length of the longest palindromic subsequence in seq     static int lps(char seq[], int i, int j) {    // Base Case 1: If there is only 1 character        if (i == j) {            return 1;        }     // Base Case 2: If there are only 2 characters and both are same        if (seq[i] == seq[j] && i + 1 == j) {            return 2;        }     // If the first and last characters match        if (seq[i] == seq[j]) {            return lps(seq, i + 1, j - 1) + 2;        }     // If the first and last characters do not match        return max(lps(seq, i, j - 1), lps(seq, i + 1, j));    }      /* Driver program to test above function */    public static void main(String[] args) {        String seq = "GEEKSFORGEEKS";        int n = seq.length();        System.out.printf("The length of the LPS is %d", lps(seq.toCharArray(), 0, n - 1));     }}
# Python 3 program of above approach # A utility function to get max# of two integersdef max(x, y):    if(x > y):        return x    return y     # Returns the length of the longest# palindromic subsequence in seqdef lps(seq, i, j):         # Base Case 1: If there is    # only 1 character    if (i == j):        return 1     # Base Case 2: If there are only 2    # characters and both are same    if (seq[i] == seq[j] and i + 1 == j):        return 2         # If the first and last characters match    if (seq[i] == seq[j]):        return lps(seq, i + 1, j - 1) + 2     # If the first and last characters    # do not match    return max(lps(seq, i, j - 1),               lps(seq, i + 1, j)) # Driver Codeif __name__ == '__main__':    seq = "GEEKSFORGEEKS"    n = len(seq)    print("The length of the LPS is",                  lps(seq, 0, n - 1))     # This code contributed by Rajput-Ji
// C# program of the above approachusing System;                     public class GFG{     // A utility function to get max of two integers    static int max(int x, int y) {        return (x > y) ? x : y;    }    // Returns the length of the longest palindromic subsequence in seq      static int lps(char []seq, int i, int j) {    // Base Case 1: If there is only 1 character        if (i == j) {            return 1;        }      // Base Case 2: If there are only 2 characters and both are same        if (seq[i] == seq[j] && i + 1 == j) {            return 2;        }      // If the first and last characters match        if (seq[i] == seq[j]) {            return lps(seq, i + 1, j - 1) + 2;        }      // If the first and last characters do not match        return max(lps(seq, i, j - 1), lps(seq, i + 1, j));    }        /* Driver program to test above function */    public static void Main() {        String seq = "GEEKSFORGEEKS";        int n = seq.Length;        Console.Write("The length of the LPS is "+lps(seq.ToCharArray(), 0, n - 1));      }} // This code is contributed by Rajput-Ji
<?php// PHP program of above approach // Returns the length of the longest// palindromic subsequence in seqfunction lps($seq, $i, $j){         // Base Case 1: If there is    // only 1 character    if ($i == $j)        return 1;         // Base Case 2: If there are only 2    // characters and both are same    if ($seq[$i] == $seq[$j] && $i + 1 == $j)        return 2;         // If the first and last characters match    if ($seq[$i] == $seq[$j])        return lps ($seq, $i + 1, $j - 1) + 2;         // If the first and last characters    // do not match    return max(lps($seq, $i, $j - 1),               lps($seq, $i + 1, $j));} // Driver Code$seq = "GEEKSFORGEEKS";$n = strlen($seq);echo "The length of the LPS is ".            lps($seq, 0, $n - 1);             // This code is contributed by ita_c?>
<script>         // A utility function to get max of two integers     function max(x, y)    {        return (x > y) ? x : y;    }         // Returns the length of the longest palindromic subsequence in seq        function lps(seq, i, j)    {        // Base Case 1: If there is only 1 character        if (i == j)        {            return 1;        }           // Base Case 2: If there are only 2 characters and both are same             if (seq[i] == seq[j] && i + 1 == j)            {                return 2;            }               // If the first and last characters match             if (seq[i] == seq[j])            {                return lps(seq, i + 1, j - 1) + 2;            }               // If the first and last characters do not match             return max(lps(seq, i, j - 1), lps(seq, i + 1, j));    }         /* Driver program to test above function */    let seq = "GEEKSFORGEEKS";    let n = seq.length;    document.write("The length of the LPS is ", lps(seq.split(""), 0, n - 1));         // This code is contributed by avanitrachhadiya2155</script>
The length of the LPS is 5
Considering the above implementation, the following is a partial recursion tree for a sequence of length 6 with all different characters.  
               L(0, 5)
             /        \ 
            /          \  
        L(1,5)          L(0,4)
       /    \            /    \
      /      \          /      \
  L(2,5)    L(1,4)  L(1,4)  L(0,3)
In the above partial recursion tree, L(1, 4) is being solved twice. If we draw the complete recursion tree, then we can see that there are many subproblems that are solved again and again. Since the same subproblems are called again, this problem has the Overlapping Subproblems property. So LPS problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, recomputations of the same subproblems can be avoided by constructing a temporary array L[][] in a bottom-up manner.Dynamic Programming Solution  
C++
Java
Python3
C#
PHP
Javascript
// A Dynamic Programming based C++ program for LPS problem// Returns the length of the longest palindromic subsequence in seq#include<stdio.h>#include<string.h> // A utility function to get max of two integersint max (int x, int y) { return (x > y)? x : y; } // Returns the length of the longest palindromic subsequence in seqint lps(char *str){   int n = strlen(str);   int i, j, cl;   int L[n][n];  // Create a table to store results of subproblems     // Strings of length 1 are palindrome of length 1   for (i = 0; i < n; i++)      L[i][i] = 1;     // Build the table. Note that the lower diagonal values of table are    // useless and not filled in the process. The values are filled in a    // manner similar to Matrix Chain Multiplication DP solution (See    // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/). cl is length of    // substring    for (cl=2; cl<=n; cl++)    {        for (i=0; i<n-cl+1; i++)        {            j = i+cl-1;            if (str[i] == str[j] && cl == 2)               L[i][j] = 2;            else if (str[i] == str[j])               L[i][j] = L[i+1][j-1] + 2;            else               L[i][j] = max(L[i][j-1], L[i+1][j]);        }    }     return L[0][n-1];} /* Driver program to test above functions */int main(){    char seq[] = "GEEKS FOR GEEKS";    int n = strlen(seq);    printf ("The length of the LPS is %d", lps(seq));    getchar();    return 0;}
// A Dynamic Programming based Java// Program for the Egg Dropping Puzzleclass LPS{     // A utility function to get max of two integers    static int max (int x, int y) { return (x > y)? x : y; }         // Returns the length of the longest    // palindromic subsequence in seq    static int lps(String seq)    {    int n = seq.length();    int i, j, cl;    // Create a table to store results of subproblems    int L[][] = new int[n][n];         // Strings of length 1 are palindrome of length 1    for (i = 0; i < n; i++)        L[i][i] = 1;                     // Build the table. Note that the lower        // diagonal values of table are        // useless and not filled in the process.        // The values are filled in a manner similar        //  to Matrix Chain Multiplication DP solution (See        // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/).        // cl is length of substring        for (cl=2; cl<=n; cl++)        {            for (i=0; i<n-cl+1; i++)            {                j = i+cl-1;                if (seq.charAt(i) == seq.charAt(j) && cl == 2)                L[i][j] = 2;                else if (seq.charAt(i) == seq.charAt(j))                L[i][j] = L[i+1][j-1] + 2;                else                L[i][j] = max(L[i][j-1], L[i+1][j]);            }        }                     return L[0][n-1];    }             /* Driver program to test above functions */    public static void main(String args[])    {        String seq = "GEEKSFORGEEKS";        int n = seq.length();        System.out.println("The length of the lps is "+ lps(seq));    }}/* This code is contributed by Rajat Mishra */
# A Dynamic Programming based Python# program for LPS problem Returns the length#  of the longest palindromic subsequence in seqdef lps(str):    n = len(str)     # Create a table to store results of subproblems    L = [[0 for x in range(n)] for x in range(n)]     # Strings of length 1 are palindrome of length 1    for i in range(n):        L[i][i] = 1     # Build the table. Note that the lower    # diagonal values of table are    # useless and not filled in the process.    # The values are filled in a    # manner similar to Matrix Chain    # Multiplication DP solution (See    # https://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/    # cl is length of substring    for cl in range(2, n+1):        for i in range(n-cl+1):            j = i+cl-1            if str[i] == str[j] and cl == 2:                L[i][j] = 2            elif str[i] == str[j]:                L[i][j] = L[i+1][j-1] + 2            else:                L[i][j] = max(L[i][j-1], L[i+1][j]);     return L[0][n-1] # Driver program to test above functionsseq = "GEEKS FOR GEEKS"n = len(seq)print("The length of the LPS is " + str(lps(seq))) # This code is contributed by Bhavya Jain
// A Dynamic Programming based C# Program// for the Egg Dropping Puzzleusing System; class GFG {     // A utility function to get max of    // two integers    static int max (int x, int y)    {        return (x > y)? x : y;    }         // Returns the length of the longest    // palindromic subsequence in seq    static int lps(string seq)    {    int n = seq.Length;    int i, j, cl;         // Create a table to store results    // of subproblems    int [,]L = new int[n,n];         // Strings of length 1 are    // palindrome of length 1    for (i = 0; i < n; i++)        L[i,i] = 1;                     // Build the table. Note that the        // lower diagonal values of table        // are useless and not filled in        // the process. The values are        // filled in a manner similar to        // Matrix Chain Multiplication DP        // solution (See        // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/        // cl is length of substring        for (cl = 2; cl <= n; cl++)        {            for (i = 0; i < n-cl+1; i++)            {                j = i + cl - 1;                                 if (seq[i] == seq[j] &&                                  cl == 2)                    L[i,j] = 2;                else if (seq[i] == seq[j])                    L[i,j] = L[i+1,j-1] + 2;                else                    L[i,j] =                     max(L[i,j-1], L[i+1,j]);            }        }                     return L[0,n-1];    }             /* Driver program to test above    functions */    public static void Main()    {        string seq = "GEEKS FOR GEEKS";        int n = seq.Length;        Console.Write("The length of the "                  + "lps is "+ lps(seq));    }} // This code is contributed by nitin mittal.
<?php// A Dynamic Programming based// PHP program for LPS problem// Returns the length of the// longest palindromic// subsequence in seq // A utility function to get// max of two integers// function max( $x, $y)// { return ($x > $y)? $x : $y; } // Returns the length of the// longest palindromic// subsequence in seqfunction lps($str){$n = strlen($str);$i; $j; $cl; // Create a table to store// results of subproblems$L[][] = array(array());  // Strings of length 1 are// palindrome of length 1for ($i = 0; $i < $n; $i++)    $L[$i][$i] = 1;     // Build the table. Note that    // the lower diagonal values    // of table are useless and    // not filled in the process.    // The values are filled in a    // manner similar to Matrix    // Chain Multiplication DP    // solution (See    // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/).    // cl is length of substring    for ($cl = 2; $cl <= $n; $cl++)    {        for ($i = 0; $i < $n - $cl + 1; $i++)        {            $j = $i + $cl - 1;            if ($str[$i] == $str[$j] &&                            $cl == 2)            $L[$i][$j] = 2;            else if ($str[$i] == $str[$j])            $L[$i][$j] = $L[$i + 1][$j - 1] + 2;            else            $L[$i][$j] = max($L[$i][$j - 1],                             $L[$i + 1][$j]);        }    }     return $L[0][$n - 1];} // Driver Code$seq = 'GEEKS FOR GEEKS';$n = strlen($seq);echo "The length of the " .      "LPS is ", lps($seq); // This code is contributed// by shiv_bhakt.?>
<script>// A Dynamic Programming based Javascript// Program for the Egg Dropping Puzzle // A utility function to get max of two integersfunction max(x,y){    return (x > y)? x : y;} // Returns the length of the longest    // palindromic subsequence in seqfunction lps(seq){    let n = seq.length;    let i, j, cl;    // Create a table to store results of subproblems    let L = new Array(n);    for(let x=0;x<n;x++)    {        L[x] = new Array(n);        for(let y = 0; y < n; y++)            L[x][y] = 0;    }          // Strings of length 1 are palindrome of length 1    for (i = 0; i < n; i++)        L[i][i] = 1;                      // Build the table. Note that the lower        // diagonal values of table are        // useless and not filled in the process.        // The values are filled in a manner similar        //  to Matrix Chain Multiplication DP solution (See        // https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/).        // cl is length of substring        for (cl = 2; cl <= n; cl++)        {            for (i = 0; i < n -cl + 1; i++)            {                j = i + cl - 1;                if (seq[i] == seq[j] && cl == 2)                    L[i][j] = 2;                else if (seq[i] == seq[j])                    L[i][j] = L[i + 1][j - 1] + 2;                else                    L[i][j] = max(L[i][j - 1], L[i + 1][j]);            }        }                      return L[0][n - 1];}  /* Driver program to test above functions */let seq = "GEEKS FOR GEEKS";let n = seq.length;document.write("The length of the lps is "+ lps(seq)); // This code is contributed by rag2127</script>
The length of the LPS is 7
The Time Complexity of the above implementation is O(n^2) which is much better than the worst-case time complexity of Naive Recursive implementation.
The idea used here is to reverse the given input string and check the length of the longest common subsequence. That would be the answer for the longest palindromic subsequence.
C++
Java
Python3
Javascript
// A Dynamic Programming based C++ program for LPS problem// Returns the length of the longest palindromic subsequence// in seq#include <bits/stdc++.h>using namespace std; int dp[1001][1001]; // Returns the length of the longest palindromic subsequence// in seqint lps(string& s1, string& s2, int n1, int n2){    if (n1 == 0 || n2 == 0) {        return 0;    }    if (dp[n1][n2] != -1) {        return dp[n1][n2];    }    if (s1[n1 - 1] == s2[n2 - 1]) {        return dp[n1][n2] = 1 + lps(s1, s2, n1 - 1, n2 - 1);    }    else {        return dp[n1][n2] = max(lps(s1, s2, n1 - 1, n2),                                lps(s1, s2, n1, n2 - 1));    }} /* Driver program to test above functions */int main(){    string seq = "GEEKS FOR GEEKS";    int n = seq.size();    dp[n][n];    memset(dp, -1, sizeof(dp));    string s2 = seq;    reverse(s2.begin(), s2.end());    cout << "The length of the LPS is "         << lps(s2, seq, n, n) << endl;    return 0;} // This code is contributed by Arun Bang
// Java program of above approachclass GFG {   // A utility function to get max of two integers  static int max(int x, int y) {    return (x > y) ? x : y;  }     // Returns the length of the longest palindromic subsequence in seq  static int lps(char seq[], int i, int j)  {         // Base Case 1: If there is only 1 character    if (i == j) {      return 1;    }     // Base Case 2: If there are only 2 characters and both are same    if (seq[i] == seq[j] && i + 1 == j) {      return 2;    }     // If the first and last characters match    if (seq[i] == seq[j]) {      return lps(seq, i + 1, j - 1) + 2;    }     // If the first and last characters do not match    return max(lps(seq, i, j - 1), lps(seq, i + 1, j));  }    /* Driver program to test above function */  public static void main(String[] args) {    String seq = "GEEKS FOR GEEKS";    int n = seq.length();    System.out.printf("The length of the LPS is %d", lps(seq.toCharArray(), 0, n - 1));   }} // This code is contributed by gauravrajput1
# A Dynamic Programming based Python program for LPS problem# Returns the length of the longest palindromic subsequence# in seq dp = [[-1 for i in range(1001)]for j in range(1001)] # Returns the length of the longest palindromic subsequence# in seqdef lps(s1, s2, n1, n2):     if (n1 == 0 or n2 == 0):        return 0     if (dp[n1][n2] != -1):        return dp[n1][n2]     if (s1[n1 - 1] == s2[n2 - 1]):        dp[n1][n2] = 1 + lps(s1, s2, n1 - 1, n2 - 1)        return dp[n1][n2]    else:        dp[n1][n2] = max(lps(s1, s2, n1 - 1, n2),lps(s1, s2, n1, n2 - 1))        return dp[n1][n2] # Driver program to test above functions seq = "GEEKS FOR GEEKS"n = len(seq) s2 = seqs2 = s2[::-1]print(f"The length of the LPS is {lps(s2, seq, n, n)}")  # This code is contributed by shinjanpatra
<script> // A Dynamic Programming based JavaScript program for LPS problem// Returns the length of the longest palindromic subsequence// in seqlet dp; // Returns the length of the longest palindromic subsequence// in seqfunction lps(s1, s2, n1, n2){    if (n1 == 0 || n2 == 0) {        return 0;    }    if (dp[n1][n2] != -1) {        return dp[n1][n2];    }    if (s1[n1 - 1] == s2[n2 - 1]) {        return dp[n1][n2] = 1 + lps(s1, s2, n1 - 1, n2 - 1);    }    else {        return dp[n1][n2] = Math.max(lps(s1, s2, n1 - 1, n2),                                lps(s1, s2, n1, n2 - 1));    }} /* Driver program to test above functions */ let seq = "GEEKS FOR GEEKS";let n = seq.length;dp = new Array(1001);for(let i=0;i<1001;i++){    dp[i] = new Array(1001).fill(-1);}let s2 = seq;s2 = s2.split('').reverse().join('');document.write("The length of the LPS is " + lps(s2, seq, n, n),"</br>");  // This code is contributed by shinjanpatra </script>
The length of the LPS is 7
Time Complexity: O(n*n) 
YouTubeGeeksforGeeks502K subscribersLongest Palindromic Subsequence | Dynamic Programming | Set 12 | GeeksforGeeksWatch laterShareCopy linkInfoShoppingTap to unmuteIf playback doesn't begin shortly, try restarting your device.More videosMore videosYou're signed outVideos you watch may be added to the TV's watch history and influence TV recommendations. To avoid this, cancel and sign in to YouTube on your computer.CancelConfirmSwitch cameraShareInclude playlistAn error occurred while retrieving sharing information. Please try again later.Watch on0:000:000:00 / 4:33•Live•<div class="player-unavailable"><h1 class="message">An error occurred.</h1><div class="submessage"><a href="https://www.youtube.com/watch?v=TLaGwTnd3HY" target="_blank">Try watching this video on www.youtube.com</a>, or enable JavaScript if it is disabled in your browser.</div></div>
Print Longest Palindromic Subsequence Longest palindrome subsequence with O(n) spacePlease write comments if you find anything incorrect, or you want to share more information about the topic discussed above.References: http://users.eecs.northwestern.edu/~dda902/336/hw6-sol.pdf 
nitin mittal
Vishal_Khoda
Rajput-Ji
Akanksha_Rai
ukasp
paperdosa
avanitrachhadiya2155
rag2127
sumitgumber28
arunbang17
amartyaghoshgfg
simmytarika5
shinjanpatra
GauravRajput1
Amazon
Linkedin
palindrome
PayPal
Rivigo
subsequence
Dynamic Programming
Strings
Amazon
Linkedin
PayPal
Rivigo
Strings
Dynamic Programming
palindrome
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Matrix Chain Multiplication | DP-8
Subset Sum Problem | DP-25
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Write a program to reverse an array or string
Reverse a string in Java
Write a program to print all permutations of a given string
C++ Data Types
Check for Balanced Brackets in an expression (well-formedness) using Stack