Given a sequence, print a longest palindromic subsequence of it.
Examples :
Input : BBABCBCAB Output : BABCBAB The above output is the longest palindromic subsequence of given sequence. "BBBBB" and "BBCBB" are also palindromic subsequences of the given sequence, but not the longest ones. Input : GEEKSFORGEEKS Output : Output can be either EEKEE or EESEE or EEGEE, ..
We have discussed a solution in below post to find length of longest palindromic subsequence.
Dynamic Programming | Set 12 (Longest Palindromic Subsequence)
Method 1:
This problem is close to the Longest Common Subsequence (LCS) problem. In fact, we can use LCS as a subroutine to solve this problem. Following is the two step solution that uses LCS.
- Reverse the given sequence and store the reverse in another array say rev[0..n-1]
- LCS of the given sequence and rev[] will be the longest palindromic sequence.
- Once we have found LCS, we can print the LCS.
Below is the implementation of above approach:
C++
/* CPP program to print longest palindromic subsequence */
#include<bits/stdc++.h> using namespace std;
/* Returns LCS X and Y */ string lcs(string &X, string &Y) { int m = X.length();
int n = Y.length();
int L[m+1][n+1];
/* Following steps build L[m+1][n+1] in bottom
up fashion. Note that L[i][j] contains
length of LCS of X[0..i-1] and Y[0..j-1] */
for ( int i=0; i<=m; i++)
{
for ( int j=0; j<=n; j++)
{
if (i == 0 || j == 0)
L[i][j] = 0;
else if (X[i-1] == Y[j-1])
L[i][j] = L[i-1][j-1] + 1;
else
L[i][j] = max(L[i-1][j], L[i][j-1]);
}
}
// Following code is used to print LCS
int index = L[m][n];
// Create a string length index+1 and
// fill it with \0
string lcs(index+1, '\0' );
// Start from the right-most-bottom-most
// corner and one by one store characters
// in lcs[]
int i = m, j = n;
while (i > 0 && j > 0)
{
// If current character in X[] and Y
// are same, then current character
// is part of LCS
if (X[i-1] == Y[j-1])
{
// Put current character in result
lcs[index-1] = X[i-1];
i--;
j--;
// reduce values of i, j and index
index--;
}
// If not same, then find the larger of
// two and go in the direction of larger
// value
else if (L[i-1][j] > L[i][j-1])
i--;
else
j--;
}
return lcs;
} // Returns longest palindromic subsequence // of str string longestPalSubseq(string &str) { // Find reverse of str
string rev = str;
reverse(rev.begin(), rev.end());
// Return LCS of str and its reverse
return lcs(str, rev);
} /* Driver program to test above function */ int main()
{ string str = "GEEKSFORGEEKS" ;
cout << longestPalSubseq(str);
return 0;
} |
Java
// Java program to print longest palindromic // subsequence import java.io.*;
class GFG {
/* Returns LCS X and Y */
static String lcs(String a, String b)
{
int m = a.length();
int n = b.length();
char X[] = a.toCharArray();
char Y[] = b.toCharArray();
int L[][] = new int [m + 1 ][n + 1 ];
/* Following steps build L[m+1][n+1] in bottom
up fashion. Note that L[i][j] contains
length of LCS of X[0..i-1] and Y[0..j-1] */
for ( int i = 0 ; i <= m; i++) {
for ( int j = 0 ; j <= n; j++) {
if (i == 0 || j == 0 ) {
L[i][j] = 0 ;
}
else if (X[i - 1 ] == Y[j - 1 ]) {
L[i][j] = L[i - 1 ][j - 1 ] + 1 ;
}
else {
L[i][j] = Math.max(L[i - 1 ][j],
L[i][j - 1 ]);
}
}
}
// Following code is used to print LCS
int index = L[m][n];
// Create a String length index+1 and
// fill it with \0
char [] lcs = new char [index + 1 ];
// Start from the right-most-bottom-most
// corner and one by one store characters
// in lcs[]
int i = m, j = n;
while (i > 0 && j > 0 ) {
// If current character in X[] and Y
// are same, then current character
// is part of LCS
if (X[i - 1 ] == Y[j - 1 ]) {
// Put current character in result
lcs[index - 1 ] = X[i - 1 ];
i--;
j--;
// reduce values of i, j and index
index--;
} // If not same, then find the larger of
// two and go in the direction of larger
// value
else if (L[i - 1 ][j] > L[i][j - 1 ]) {
i--;
}
else {
j--;
}
}
String ans = "" ;
for ( int x = 0 ; x < lcs.length; x++) {
ans += lcs[x];
}
return ans;
}
// Returns longest palindromic subsequence
// of str
static String longestPalSubseq(String str)
{
// Find reverse of str
String rev = str;
rev = reverse(rev);
// Return LCS of str and its reverse
return lcs(str, rev);
}
static String reverse(String str)
{
String ans = "" ;
// convert String to character array
// by using toCharArray
char [] try1 = str.toCharArray();
for ( int i = try1.length - 1 ; i >= 0 ; i--) {
ans += try1[i];
}
return ans;
}
/* Driver program to test above function */
public static void main(String[] args)
{
String str = "GEEKSFORGEEKS" ;
System.out.println(longestPalSubseq(str));
}
} |
Python3
# Python3 program to print longest # palindromic subsequence # Returns LCS X and Y def lcs_(X, Y) :
m = len (X)
n = len (Y)
L = [[ 0 ] * (n + 1 )] * (m + 1 )
# Following steps build L[m+1][n+1]
# in bottom up fashion. Note that
# L[i][j] contains length of LCS of
# X[0..i-1] and Y[0..j-1]
for i in range (n + 1 ) :
for j in range (n + 1 ) :
if (i = = 0 or j = = 0 ) :
L[i][j] = 0 ;
elif (X[i - 1 ] = = Y[j - 1 ]) :
L[i][j] = L[i - 1 ][j - 1 ] + 1 ;
else :
L[i][j] = max (L[i - 1 ][j],
L[i][j - 1 ]);
# Following code is used to print LCS
index = L[m][n];
# Create a string length index+1 and
# fill it with \0
lcs = [ "\n " ] * (index + 1 )
# Start from the right-most-bottom-most
# corner and one by one store characters
# in lcs[]
i, j = m, n
while (i > 0 and j > 0 ) :
# If current character in X[] and Y
# are same, then current character
# is part of LCS
if (X[i - 1 ] = = Y[j - 1 ]) :
# Put current character in result
lcs[index - 1 ] = X[i - 1 ]
i - = 1
j - = 1
# reduce values of i, j and index
index - = 1
# If not same, then find the larger of
# two and go in the direction of larger
# value
elif (L[i - 1 ][j] > L[i][j - 1 ]) :
i - = 1
else :
j - = 1
ans = ""
for x in range ( len (lcs)) :
ans + = lcs[x]
return ans
# Returns longest palindromic # subsequence of str def longestPalSubseq(string) :
# Find reverse of str
rev = string[: : - 1 ]
# Return LCS of str and its reverse
return lcs_(string, rev)
# Driver Code if __name__ = = "__main__" :
string = "GEEKSFORGEEKS" ;
print (longestPalSubseq(string))
# This code is contributed by Ryuga |
C#
// C# program to print longest palindromic //subsequence using System;
public class GFG {
/* Returns LCS X and Y */
static String lcs(String a, String b) {
int m = a.Length;
int n = b.Length;
char []X = a.ToCharArray();
char []Y = b.ToCharArray();
int [,]L = new int [m + 1,n + 1];
int i, j;
/* Following steps build L[m+1,n+1] in bottom
up fashion. Note that L[i,j] contains
length of LCS of X[0..i-1] and Y[0..j-1] */
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
L[i,j] = 0;
} else if (X[i - 1] == Y[j - 1]) {
L[i,j] = L[i - 1,j - 1] + 1;
} else {
L[i,j] = Math.Max(L[i - 1,j], L[i,j - 1]);
}
}
}
// Following code is used to print LCS
int index = L[m,n];
// Create a String length index+1 and
// fill it with \0
char [] lcs = new char [index + 1];
// Start from the right-most-bottom-most
// corner and one by one store characters
// in lcs[]
i = m; j = n;
while (i > 0 && j > 0) {
// If current character in X[] and Y
// are same, then current character
// is part of LCS
if (X[i - 1] == Y[j - 1]) {
// Put current character in result
lcs[index - 1] = X[i - 1];
i--;
j--;
// reduce values of i, j and index
index--;
} // If not same, then find the larger of
// two and go in the direction of larger
// value
else if (L[i - 1,j] > L[i,j - 1]) {
i--;
} else {
j--;
}
}
String ans = "" ;
for ( int x = 0; x < lcs.Length; x++) {
ans += lcs[x];
}
return ans;
}
// Returns longest palindromic subsequence // of str static String longestPalSubseq(String str) {
// Find reverse of str
String rev = str;
rev = reverse(rev);
// Return LCS of str and its reverse
return lcs(str, rev);
}
static String reverse(String str) {
String ans = "" ;
// convert String to character array
// by using toCharArray
char [] try1 = str.ToCharArray();
for ( int i = try1.Length - 1; i >= 0; i--) {
ans += try1[i];
}
return ans;
}
/* Driver program to test above function */
public static void Main() {
String str = "GEEKSFORGEEKS" ;
Console.Write(longestPalSubseq(str));
}
} // This code is contributed by 29AjayKumar |
Javascript
<script> // Javascript program to print longest palindromic subsequence
/* Returns LCS X and Y */
function lcs(a, b) {
let m = a.length;
let n = b.length;
let X = a.split( '' );
let Y = b.split( '' );
let L = new Array(m + 1);
for (let i = 0; i <= m; i++) {
L[i] = new Array(n + 1);
for (let j = 0; j <= n; j++) {
L[i][j] = 0;
}
}
/* Following steps build L[m+1][n+1] in bottom
up fashion. Note that L[i][j] contains
length of LCS of X[0..i-1] and Y[0..j-1] */
for (let i = 0; i <= m; i++) {
for (let j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
L[i][j] = 0;
} else if (X[i - 1] == Y[j - 1]) {
L[i][j] = L[i - 1][j - 1] + 1;
} else {
L[i][j] = Math.max(L[i - 1][j], L[i][j - 1]);
}
}
}
// Following code is used to print LCS
let index = L[m][n];
// Create a String length index+1 and
// fill it with \0
let lcs = new Array(index + 1);
lcs.fill( '' );
// Start from the right-most-bottom-most
// corner and one by one store characters
// in lcs[]
let i = m, j = n;
while (i > 0 && j > 0) {
// If current character in X[] and Y
// are same, then current character
// is part of LCS
if (X[i - 1] == Y[j - 1]) {
// Put current character in result
lcs[index - 1] = X[i - 1];
i--;
j--;
// reduce values of i, j and index
index--;
} // If not same, then find the larger of
// two and go in the direction of larger
// value
else if (L[i - 1][j] > L[i][j - 1]) {
i--;
} else {
j--;
}
}
let ans = "" ;
for (let x = 0; x < lcs.length; x++) {
ans += lcs[x];
}
return ans;
}
// Returns longest palindromic subsequence // of str function longestPalSubseq(str) {
// Find reverse of str
let rev = str;
rev = reverse(rev);
// Return LCS of str and its reverse
return lcs(str, rev);
}
function reverse(str) {
let ans = "" ;
// convert String to character array
// by using toCharArray
let try1 = str.split( '' );
for (let i = try1.length - 1; i >= 0; i--) {
ans += try1[i];
}
return ans;
}
let str = "GEEKSFORGEEKS" ;
document.write(longestPalSubseq(str));
// This code is contributed by suresh07.
</script> |
Output:
EEGEE
Time Complexity: O(n*m)
Auxiliary Space: O(n*m)