📜  打印最长的公共子序列设置2(全部打印)

📅  最后修改于: 2021-05-07 08:37:45             🧑  作者: Mango

给定两个序列,请打印两个序列中存在的所有最长子序列。

例子:

Input: 
string X = "AGTGATG"
string Y = "GTTAG"
Output: 
GTAG
GTTG

Input: 
string X = "AATCC"
string Y = "ACACG"
Output:  
ACC
AAC

Input: 
string X = "ABCBDAB"
string Y = "BDCABA"
Output:  
BCAB
BCBA
BDAB

我们在这里讨论了最长公共子序列(LCS)问题。此处讨论的函数主要是查找LCS的长度。我们还讨论了如何在此处打印最长的子序列。但是由于两个字符串的LCS不是唯一的,因此在本文中,我们将打印出解决LCS问题的所有可能解决方案。

以下是打印所有LCS的详细算法。

我们按照上一篇文章中的讨论构造L [m + 1] [n + 1]表,并从L [m] [n]开始遍历2D数组。对于矩阵中的当前单元格L [i] [j],

a)如果X和Y的最后一个字符相同(即X [i-1] == Y [j-1]),则该字符必须出现在子字符串X [0…i-1]的所有LCS中,并且Y [0..j-1]。我们简单地对矩阵中的L [i-1] [j-1]进行递归,然后将当前字符附加到子字符串X [0…i-2]和Y [0..j-2]的所有LCS中。

b)如果X和Y的最后一个字符不相同(即X [i-1]!= Y [j-1]),则可以从矩阵的任一顶面构造LCS(即L [i-1] ] [j])还是从矩阵的左侧开始(即L [i] [j-1]),具体取决于哪个值更大。如果两个值相等(即L [i-1] [j] == L [i] [j-1]),则将从矩阵的两侧构造它。因此,基于L [i-1] [j]和L [i] [j-1]的值,我们朝更大的方向前进,或者在两个方向相等的情况下朝两个方向前进。

以下是上述想法的递归实现–

C++
/* Dynamic Programming implementation of LCS problem */
#include 
using namespace std;
  
// Maximum string length
#define N 100
  
int L[N][N];
  
/* Returns set containing all LCS for X[0..m-1], Y[0..n-1] */
set findLCS(string X, string Y, int m, int n)
{
    // construct a set to store possible LCS
    set s;
  
    // If we reaches end of either string, return
    // a empty set
    if (m == 0 || n == 0)
    {
        s.insert("");
        return s;
    }
  
    // If the last characters of X and Y are same
    if (X[m - 1] == Y[n - 1])
    {
        // recurse for X[0..m-2] and Y[0..n-2] in
        // the matrix
        set tmp = findLCS(X, Y, m - 1, n - 1);
  
        // append current character to all possible LCS
        // of substring X[0..m-2] and Y[0..n-2].
        for (string str : tmp)
            s.insert(str + X[m - 1]);
    }
  
    // If the last characters of X and Y are not same
    else
    {
        // If LCS can be constructed from top side of
        // the matrix, recurse for X[0..m-2] and Y[0..n-1]
        if (L[m - 1][n] >= L[m][n - 1])
            s = findLCS(X, Y, m - 1, n);
  
        // If LCS can be constructed from left side of
        // the matrix, recurse for X[0..m-1] and Y[0..n-2]
        if (L[m][n - 1] >= L[m - 1][n])
        {
            set tmp = findLCS(X, Y, m, n - 1);
  
            // merge two sets if L[m-1][n] == L[m][n-1]
            // Note s will be empty if L[m-1][n] != L[m][n-1]
            s.insert(tmp.begin(), tmp.end());
        }
    }
    return s;
}
  
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
int LCS(string X, string Y, int m, int n)
{
    // Build L[m+1][n+1] in bottom up fashion
    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]);
        }
    }
    return L[m][n];
}
  
/* Driver program to test above function */
int main()
{
    string X = "AGTGATG";
    string Y = "GTTAG";
    int m = X.length();
    int n = Y.length();
  
    cout << "LCS length is " << LCS(X, Y, m, n) << endl;
  
    set s = findLCS(X, Y, m, n);
  
    for (string str : s)
        cout << str << endl;
  
    return 0;
}


Java
/* Dynamic Programming implementation of LCS problem */
import java.util.*;
class GFG
{
  
// Maximum String length
static int N = 100;
  
static int [][]L = new int[N][N];
  
/* Returns set containing all LCS for 
   X[0..m-1], Y[0..n-1] */
static Set findLCS(String X, 
                           String Y, int m, int n)
{
    // construct a set to store possible LCS
    Set s = new HashSet<>();
  
    // If we reaches end of either String, 
    // return a empty set
    if (m == 0 || n == 0)
    {
        s.add("");
        return s;
    }
  
    // If the last characters of X and Y are same
    if (X.charAt(m - 1) == Y.charAt(n - 1))
    {
        // recurse for X[0..m-2] and Y[0..n-2] 
        // in the matrix
        Set tmp = findLCS(X, Y, m - 1, n - 1);
  
        // append current character to all possible LCS
        // of subString X[0..m-2] and Y[0..n-2].
        for (String str : tmp)
            s.add(str + X.charAt(m - 1));
    }
  
    // If the last characters of X and Y are not same
    else
    {
        // If LCS can be constructed from top side of
        // the matrix, recurse for X[0..m-2] and Y[0..n-1]
        if (L[m - 1][n] >= L[m][n - 1])
            s = findLCS(X, Y, m - 1, n);
  
        // If LCS can be constructed from left side of
        // the matrix, recurse for X[0..m-1] and Y[0..n-2]
        if (L[m][n - 1] >= L[m - 1][n])
        {
            Set tmp = findLCS(X, Y, m, n - 1);
  
            // merge two sets if L[m-1][n] == L[m][n-1]
            // Note s will be empty if L[m-1][n] != L[m][n-1]
            s.addAll(tmp);
        }
    }
    return s;
}
  
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
static int LCS(String X, String Y, int m, int n)
{
    // Build L[m+1][n+1] in bottom up fashion
    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.charAt(i - 1) == Y.charAt(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]);
        }
    }
    return L[m][n];
}
  
// Driver Code
public static void main(String[] args)
{
    String X = "AGTGATG";
    String Y = "GTTAG";
    int m = X.length();
    int n = Y.length();
  
    System.out.println("LCS length is " +
                        LCS(X, Y, m, n));
  
    Set s = findLCS(X, Y, m, n);
  
    for (String str : s)
        System.out.println(str);
}
}
  
// This code is contributed by 29AjayKumar


Python3
# Dynamic Programming implementation of LCS problem
  
# Maximum string length
N = 100
L = [[0 for i in range(N)] 
        for j in range(N)]
  
# Returns set containing all LCS 
# for X[0..m-1], Y[0..n-1]
def findLCS(x, y, m, n):
  
    # construct a set to store possible LCS
    s = set()
  
    # If we reaches end of either string, return
    # a empty set
    if m == 0 or n == 0:
        s.add("")
        return s
  
    # If the last characters of X and Y are same
    if x[m - 1] == y[n - 1]:
  
        # recurse for X[0..m-2] and Y[0..n-2] in
        # the matrix
        tmp = findLCS(x, y, m - 1, n - 1)
  
        # append current character to all possible LCS
        # of substring X[0..m-2] and Y[0..n-2].
        for string in tmp:
            s.add(string + x[m - 1])
  
    # If the last characters of X and Y are not same
    else:
  
        # If LCS can be constructed from top side of
        # the matrix, recurse for X[0..m-2] and Y[0..n-1]
        if L[m - 1][n] >= L[m][n - 1]:
            s = findLCS(x, y, m - 1, n)
  
        # If LCS can be constructed from left side of
        # the matrix, recurse for X[0..m-1] and Y[0..n-2]
        if L[m][n - 1] >= L[m - 1][n]:
            tmp = findLCS(x, y, m, n - 1)
  
            # merge two sets if L[m-1][n] == L[m][n-1]
            # Note s will be empty if L[m-1][n] != L[m][n-1]
            for i in tmp:
                s.add(i)
    return s
  
# Returns length of LCS for X[0..m-1], Y[0..n-1]
def LCS(x, y, m, n):
  
    # Build L[m+1][n+1] in bottom up fashion
    for i in range(m + 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])
    return L[m][n]
  
# Driver Code
if __name__ == "__main__":
    x = "AGTGATG"
    y = "GTTAG"
    m = len(x)
    n = len(y)
  
    print("LCS length is", LCS(x, y, m, n))
  
    s = findLCS(x, y, m, n)
      
    for i in s:
        print(i)
  
# This code is contributed by
# sanjeev2552


C#
// Dynamic Programming implementation 
// of LCS problem 
using System;
using System.Collections.Generic; 
      
class GFG
{
  
// Maximum String length
static int N = 100;
  
static int [,]L = new int[N, N];
  
/* Returns set containing all LCS for 
X[0..m-1], Y[0..n-1] */
static HashSet findLCS(String X, 
                               String Y,
                               int m, int n)
{
    // construct a set to store possible LCS
    HashSet s = new HashSet();
  
    // If we reaches end of either String, 
    // return a empty set
    if (m == 0 || n == 0)
    {
        s.Add("");
        return s;
    }
  
    // If the last characters of X and Y are same
    if (X[m - 1] == Y[n - 1])
    {
        // recurse for X[0..m-2] and Y[0..n-2] 
        // in the matrix
        HashSet tmp = findLCS(X, Y, m - 1, n - 1);
  
        // append current character to all possible LCS
        // of subString X[0..m-2] and Y[0..n-2].
        foreach (String str in tmp)
            s.Add(str + X[m - 1]);
    }
  
    // If the last characters of X and Y are not same
    else
    {
        // If LCS can be constructed from top side of
        // the matrix, recurse for X[0..m-2] and Y[0..n-1]
        if (L[m - 1, n] >= L[m, n - 1])
            s = findLCS(X, Y, m - 1, n);
  
        // If LCS can be constructed from left side of
        // the matrix, recurse for X[0..m-1] and Y[0..n-2]
        if (L[m, n - 1] >= L[m - 1, n])
        {
            HashSet tmp = findLCS(X, Y, m, n - 1);
  
            // merge two sets if L[m-1,n] == L[m,n-1]
            // Note s will be empty if L[m-1,n] != L[m,n-1]
            foreach (String str in tmp)
                s.Add(str);
        }
    }
    return s;
}
  
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
static int LCS(String X, String Y, int m, int n)
{
    // Build L[m+1,n+1] in bottom up fashion
    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]);
        }
    }
    return L[m, n];
}
  
// Driver Code
public static void Main(String[] args)
{
    String X = "AGTGATG";
    String Y = "GTTAG";
    int m = X.Length;
    int n = Y.Length;
  
    Console.WriteLine("LCS length is " +
                       LCS(X, Y, m, n));
  
    HashSet s = findLCS(X, Y, m, n);
  
    foreach (String str in s)
        Console.WriteLine(str);
}
}
      
// This code is contributed by Rajput-Ji


输出:

LCS length is 4
GTAG
GTTG

参考:Wikibooks –读取所有LCS