Longest palindrome subsequence with O(n) space
Last Updated :
29 Mar, 2024
Given a sequence, find the length of the longest palindromic subsequence in it.
Examples:
Input : abbaab
Output : 4
Input : geeksforgeeks
Output : 5
We have discussed a Dynamic Programming solution for Longest Palindromic Subsequence which is based on below recursive formula.
// 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
The solution discussed above takes O(n2) extra space. In this post a space optimized solution is discussed that requires O(n) extra space. The idea is to create a one dimensional array a[] of same size as given string. We make sure that a[i] stores length of longest palindromic subsequence of prefix ending with i (or substring s[0..i]).
C++
// A Space optimized Dynamic Programming based C++
// program for LPS problem
#include <bits/stdc++.h>
using namespace std;
// Returns the length of the longest palindromic
// subsequence in str
int lps(string &s)
{
int n = s.length();
// a[i] is going to store length of longest
// palindromic subsequence of substring s[0..i]
int a[n];
// Pick starting point
for (int i = n - 1; i >= 0; i--) {
int back_up = 0;
// Pick ending points and see if s[i]
// increases length of longest common
// subsequence ending with s[j].
for (int j = i; j < n; j++) {
// similar to 2D array L[i][j] == 1
// i.e., handling substrings of length
// one.
if (j == i)
a[j] = 1;
// Similar to 2D array L[i][j] = L[i+1][j-1]+2
// i.e., handling case when corner characters
// are same.
else if (s[i] == s[j])
{
// value a[j] is depend upon previous
// unupdated value of a[j-1] but in
// previous loop value of a[j-1] is
// changed. To store the unupdated
// value of a[j-1] back_up variable
// is used.
int temp = a[j];
a[j] = back_up + 2;
back_up = temp;
}
// similar to 2D array L[i][j] = max(L[i][j-1],
// a[i+1][j])
else
{
back_up = a[j];
a[j] = max(a[j - 1], a[j]);
}
}
}
return a[n - 1];
}
/* Driver program to test above functions */
int main()
{
string str = "GEEKSFORGEEKS";
cout << lps(str);
return 0;
}
Java
// A Space optimized Dynamic Programming
// based Java program for LPS problem
class GFG {
// Returns the length of the longest
// palindromic subsequence in str
static int lps(String s)
{
int n = s.length();
// a[i] is going to store length
// of longest palindromic subsequence
// of substring s[0..i]
int a[] = new int[n];
// Pick starting point
for (int i = n - 1; i >= 0; i--)
{
int back_up = 0;
// Pick ending points and see if s[i]
// increases length of longest common
// subsequence ending with s[j].
for (int j = i; j < n; j++) {
// similar to 2D array L[i][j] == 1
// i.e., handling substrings of length
// one.
if (j == i)
a[j] = 1;
// Similar to 2D array L[i][j] = L[i+1][j-1]+2
// i.e., handling case when corner characters
// are same.
else if (s.charAt(i) == s.charAt(j))
{
int temp = a[j];
a[j] = back_up + 2;
back_up = temp;
}
// similar to 2D array L[i][j] = max(L[i][j-1],
// a[i+1][j])
else
{
back_up = a[j];
a[j] = Math.max(a[j - 1], a[j]);
}
}
}
return a[n - 1];
}
/* Driver program to test above functions */
public static void main(String[] args)
{
String str = "GEEKSFORGEEKS";
System.out.println(lps(str));
}
}
//
Python3
# A Space optimized Dynamic Programming
# based Python3 program for LPS problem
# Returns the length of the longest
# palindromic subsequence in str
def lps(s):
n = len(s)
# a[i] is going to store length
# of longest palindromic subsequence
# of substring s[0..i]
a = [0] * n
# Pick starting point
for i in range(n-1, -1, -1):
back_up = 0
# Pick ending points and see if s[i]
# increases length of longest common
# subsequence ending with s[j].
for j in range(i, n):
# similar to 2D array L[i][j] == 1
# i.e., handling substrings of length
# one.
if j == i:
a[j] = 1
# Similar to 2D array L[i][j] = L[i+1][j-1]+2
# i.e., handling case when corner characters
# are same.
elif s[i] == s[j]:
temp = a[j]
a[j] = back_up + 2
back_up = temp
# similar to 2D array L[i][j] = max(L[i][j-1],
# a[i+1][j])
else:
back_up = a[j]
a[j] = max(a[j - 1], a[j])
return a[n - 1]
# Driver Code
string = "GEEKSFORGEEKS"
print(lps(string))
# This code is contributed by Ansu Kumari.
C#
// A Space optimized Dynamic Programming
// based C# program for LPS problem
using System;
class GFG {
// Returns the length of the longest
// palindromic subsequence in str
static int lps(string s)
{
int n = s.Length;
// a[i] is going to store length
// of longest palindromic subsequence
// of substring s[0..i]
int []a = new int[n];
// Pick starting point
for (int i = n - 1; i >= 0; i--)
{
int back_up = 0;
// Pick ending points and see if s[i]
// increases length of longest common
// subsequence ending with s[j].
for (int j = i; j < n; j++) {
// similar to 2D array L[i][j] == 1
// i.e., handling substrings of length
// one.
if (j == i)
a[j] = 1;
// Similar to 2D array L[i][j] = L[i+1][j-1]+2
// i.e., handling case when corner characters
// are same.
else if (s[i] == s[j])
{
int temp = a[j];
a[j] = back_up + 2;
back_up = temp;
}
// similar to 2D array L[i][j] = max(L[i][j-1],
// a[i+1][j])
else
{
back_up = a[j];
a[j] = Math.Max(a[j - 1], a[j]);
}
}
}
return a[n - 1];
}
// Driver program
public static void Main()
{
string str = "GEEKSFORGEEKS";
Console.WriteLine(lps(str));
}
}
// This code is contributed by vt_m.
PHP
<?php
// A Space optimized Dynamic
// Programming based PHP
// program for LPS problem
// Returns the length of
// the longest palindromic .
// subsequence in str
function lps($s)
{
$n = strlen($s);
// Pick starting point
for ($i = $n - 1;
$i >= 0; $i--)
{
$back_up = 0;
// Pick ending points and
// see if s[i] increases
// length of longest common
// subsequence ending with s[j].
for ($j = $i; $j < $n; $j++)
{
// similar to 2D array
// L[i][j] == 1 i.e.,
// handling substrings
// of length one.
if ($j == $i)
$a[$j] = 1;
// Similar to 2D array
// L[i][j] = L[i+1][j-1]+2
// i.e., handling case when
// corner characters are same.
else if ($s[$i] == $s[$j])
{
// value a[j] is depend
// upon previous unupdated
// value of a[j-1] but in
// previous loop value of
// a[j-1] is changed. To
// store the unupdated value
// of a[j-1] back_up variable
// is used.
$temp = $a[$j];
$a[$j] = $back_up + 2;
$back_up = $temp;
}
// similar to 2D array
// L[i][j] = max(L[i][j-1],
// a[i+1][j])
else
{
$back_up = $a[$j];
$a[$j] = max($a[$j - 1],
$a[$j]);
}
}
}
return $a[$n - 1];
}
// Driver Code
$str = "GEEKSFORGEEKS";
echo lps($str);
// This code is contributed
// by shiv_bhakt.
?>
JavaScript
<script>
// A Space optimized Dynamic Programming
// based Python3 program for LPS problem
// Returns the length of the longest
// palindromic subsequence in str
function lps(s){
let n = s.length
// a[i] is going to store length
// of longest palindromic subsequence
// of substring s[0..i]
let a = new Array(n).fill(0);
// Pick starting point
for(let i = n - 1; i >= 0; i--){
let back_up = 0
// Pick ending points and see if s[i]
// increases length of longest common
// subsequence ending with s[j].
for (let j = i; j < n; j++){
// similar to 2D array L[i][j] == 1
// i.e., handling substrings of length
// one.
if(j == i)
a[j] = 1
// Similar to 2D array L[i][j] = L[i+1][j-1]+2
// i.e., handling case when corner characters
// are same.
else if(s[i] == s[j]){
let temp = a[j]
a[j] = back_up + 2
back_up = temp
}
// similar to 2D array L[i][j] = max(L[i][j-1],
// a[i+1][j])
else{
back_up = a[j]
a[j] = Math.max(a[j - 1], a[j])
}
}
}
return a[n - 1]
}
// Driver Code
let string = "GEEKSFORGEEKS"
document.write(lps(string),"</br>")
// This code is contributed by shinjanpatra
</script>
5
Time Complexity : O(n*n) Auxiliary Space : O(n)