给定一个序列,找到其中最长回文子序列的长度。
作为另一个示例,如果给定序列为“ BBABCBCAB”,则输出应为7,因为“ BABCBAB”是其中最长的回文子序列。 “ BBBBB”和“ BBCBB”也是给定序列的回文序列,但不是最长的。
这个问题的幼稚解决方案是生成给定序列的所有子序列,并找到最长的回文子序列。该解决方案在时间复杂度方面是指数级的。让我们看看这个问题如何同时具有动态编程(DP)问题的两个重要属性,以及如何使用动态编程有效地解决。
1)最佳子结构:
令X [0..n-1]为长度n的输入序列,L(0,n-1)为X [0..n-1]的最长回文子序列的长度。
如果X的最后一个字符和第一个字符相同,则L(0,n-1)= L(1,n-2)+ 2。
否则L(0,n-1)= MAX(L(1,n-1),L(0,n-2))。
以下是处理所有情况的通用递归解决方案。
// 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)重叠子问题
以下是LPS问题的简单递归实现。该实现仅遵循上述递归结构。
C++
// C++ program of above approach
#include
using namespace std;
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
// Returns the length of the longest palindromic subsequence in seq
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 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
// C program of above approach
#include
#include
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
// Returns the length of the longest palindromic subsequence in seq
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 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
//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));
}
}
Python3
# Python 3 program of above approach
# A utility function to get max
# of two egers
def max(x, y):
if(x > y):
return x
return y
# Returns the length of the longest
# palindromic subsequence in seq
def 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 Code
if __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#
// C# program of the above approach
using 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
Javascript
C++
// A Dynamic Programming based C++ program for LPS problem
// Returns the length of the longest palindromic subsequence in seq
#include
#include
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
// Returns the length of the longest palindromic subsequence in seq
int 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 lentgh 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
Java
// A Dynamic Programming based Java
// Program for the Egg Dropping Puzzle
class 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 lentgh 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
Python
# A Dynamic Programming based Python
# program for LPS problem Returns the length
# of the longest palindromic subsequence in seq
def 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 functions
seq = "GEEKS FOR GEEKS"
n = len(seq)
print("The length of the LPS is " + str(lps(seq)))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming based C# Program
// for the Egg Dropping Puzzle
using 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 lentgh 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
$y)? $x : $y; }
// Returns the length of the
// longest palindromic
// subsequence in seq
function 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 lentgh 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 Code
$seq = 'GEEKS FOR GEEKS';
$n = strlen($seq);
echo "The length of the " .
"LPS is ", lps($seq);
// This code is contributed
// by shiv_bhakt.
?>
输出:
The length of the LPS is 5
考虑到以上实现,以下是具有所有不同字符的长度为6的序列的部分递归树。
L(0, 5)
/ \
/ \
L(1,5) L(0,4)
/ \ / \
/ \ / \
L(2,5) L(1,4) L(1,4) L(0,3)
在上面的部分递归树中,L(1,4)被求解两次。如果绘制完整的递归树,则可以看到有很多子问题可以一次又一次地解决。由于再次调用了相同的子问题,因此此问题具有“重叠子问题”属性。因此,LPS问题具有动态编程问题的两个属性(请参阅此内容)。像其他典型的动态编程(DP)问题一样,可以通过自下而上的方式构造临时数组L [] []来避免相同子问题的重新计算。
动态编程解决方案
C++
// A Dynamic Programming based C++ program for LPS problem
// Returns the length of the longest palindromic subsequence in seq
#include
#include
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
// Returns the length of the longest palindromic subsequence in seq
int 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 lentgh 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
Java
// A Dynamic Programming based Java
// Program for the Egg Dropping Puzzle
class 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 lentgh 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
Python
# A Dynamic Programming based Python
# program for LPS problem Returns the length
# of the longest palindromic subsequence in seq
def 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 functions
seq = "GEEKS FOR GEEKS"
n = len(seq)
print("The length of the LPS is " + str(lps(seq)))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming based C# Program
// for the Egg Dropping Puzzle
using 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 lentgh 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
$y)? $x : $y; }
// Returns the length of the
// longest palindromic
// subsequence in seq
function 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 lentgh 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 Code
$seq = 'GEEKS FOR GEEKS';
$n = strlen($seq);
echo "The length of the " .
"LPS is ", lps($seq);
// This code is contributed
// by shiv_bhakt.
?>
输出:
The length of the LPS is 7
上述实现的时间复杂度为O(n ^ 2),这比Naive Recursive实现的最坏情况下的时间复杂度要好得多。