📜  LCS空间优化解决方案

📅  最后修改于: 2021-09-22 09:47:25             🧑  作者: Mango

给定两个字符串,找出它们中存在的最长子序列的长度。

例子:

LCS for input Sequences “ABCDGH” and “AEDFHR” is “ADH” of length 3. 
LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.

我们已经讨论了一个典型的基于动态规划的 LCS 解决方案。我们可以优化 LCS 问题使用的空间。我们知道 LCS 问题的递推关系是

CPP
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
int lcs(string &X, string &Y)
{
    int m = X.length(), 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]);
        }
    }
 
    /* L[m][n] contains length of LCS for X[0..n-1] and
       Y[0..m-1] */
    return L[m][n];
}


C++
// Space optimized C++ implementation
// of LCS problem
#include
using namespace std;
 
// Returns length of LCS
// for X[0..m-1], Y[0..n-1]
int lcs(string &X, string &Y)
{
     
    // Find lengths of two strings
    int m = X.length(), n = Y.length();
 
    int L[2][n + 1];
 
    // Binary index, used to
    // index current row and
    // previous row.
    bool bi;
 
    for (int i = 0; i <= m; i++)
    {
         
        // Compute current
        // binary index
        bi = i & 1;
 
        for (int j = 0; j <= n; j++)
        {
            if (i == 0 || j == 0)
                L[bi][j] = 0;
 
            else if (X[i-1] == Y[j-1])
                 L[bi][j] = L[1 - bi][j - 1] + 1;
 
            else
                L[bi][j] = max(L[1 - bi][j],
                               L[bi][j - 1]);
        }
    }
 
    // Last filled entry contains
    // length of LCS
    // for X[0..n-1] and Y[0..m-1]
    return L[bi][n];
}
 
// Driver code
int main()
{
    string X = "AGGTAB";
    string Y = "GXTXAYB";
 
    printf("Length of LCS is %d\n", lcs(X, Y));
 
    return 0;
}


Java
// Java Code for A Space Optimized
// Solution of LCS
 
class GFG {
     
    // Returns length of LCS
    // for X[0..m - 1],
    // Y[0..n - 1]
    public static int lcs(String X,
                          String Y)
    {
         
        // Find lengths of two strings
        int m = X.length(), n = Y.length();
     
        int L[][] = new int[2][n+1];
     
        // Binary index, used to index
        // current row and previous row.
        int bi=0;
     
        for (int i = 0; i <= m; i++)
        {
             
            // Compute current binary index
            bi = i & 1;
     
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    L[bi][j] = 0;
     
                else if (X.charAt(i - 1) ==
                         Y.charAt(j - 1))
                    L[bi][j] = L[1 - bi][j - 1] + 1;
     
                else
                    L[bi][j] = Math.max(L[1 - bi][j],
                                        L[bi][j - 1]);
            }
        }
     
        // Last filled entry contains length of
        // LCS for X[0..n-1] and Y[0..m-1]
        return L[bi][n];
    }
     
     
    // Driver Code
    public static void main(String[] args)
    {
        String X = "AGGTAB";
        String Y = "GXTXAYB";
     
        System.out.println("Length of LCS is " +
                                    lcs(X, Y));
    }
}
 
// This code is contributed by Arnav Kr. Mandal.


Python3
# Space optimized Python
# implementation of LCS problem
 
# Returns length of LCS for
# X[0..m-1], Y[0..n-1]
def lcs(X, Y):
     
    # Find lengths of two strings
    m = len(X)
    n = len(Y)
 
    L = [[0 for i in range(n+1)] for j in range(2)]
 
    # Binary index, used to index current row and
    # previous row.
    bi = bool
     
    for i in range(m):
        # Compute current binary index
        bi = i&1
 
        for j in range(n+1):
            if (i == 0 or j == 0):
                L[bi][j] = 0
 
            elif (X[i] == Y[j - 1]):
                L[bi][j] = L[1 - bi][j - 1] + 1
 
            else:
                L[bi][j] = max(L[1 - bi][j],
                               L[bi][j - 1])
 
    # Last filled entry contains length of LCS
    # for X[0..n-1] and Y[0..m-1]
    return L[bi][n]
 
# Driver Code
X = "AGGTAB"
Y = "GXTXAYB"
 
print("Length of LCS is", lcs(X, Y))
 
# This code is contributed by Soumen Ghosh.


C#
// C# Code for A Space
// Optimized Solution of LCS
using System;
 
class GFG
{
     
    // Returns length of LCS
    // for X[0..m - 1],
    // Y[0..n - 1]
    public static int lcs(string X,
                          string Y)
    {
         
        // Find lengths of
        // two strings
        int m = X.Length, n = Y.Length;
     
        int [,]L = new int[2, n + 1];
     
        // Binary index, used to
        // index current row and
        // previous row.
        int bi = 0;
     
        for (int i = 0; i <= m; i++)
        {
             
            // Compute current
            // binary index
            bi = i & 1;
     
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    L[bi, j] = 0;
      
                else if (X[i - 1] == Y[j - 1])
                    L[bi, j] = L[1 - bi,
                                 j - 1] + 1;
     
                else
                    L[bi, j] = Math.Max(L[1 - bi, j],
                                        L[bi, j - 1]);
            }
        }
     
        // Last filled entry contains
        // length of LCS for X[0..n-1]
        // and Y[0..m-1]
        return L[bi, n];
    }
     
    // Driver Code
    public static void Main()
    {
        string X = "AGGTAB";
        string Y = "GXTXAYB";
     
        Console.Write("Length of LCS is " +
                                lcs(X, Y));
    }
}
 
// This code is contributed
// by shiv_bhakt.


PHP


Javascript


如何找到 LCS 的长度是 O(n) 辅助空间?

我们强烈建议您在继续解决方案之前单击此处进行练习。
上述简单实现中的一个重要观察结果是,在外循环的每次迭代中,我们只需要来自前一行的所有列的值。所以不需要在我们的 DP 矩阵中存储所有行,我们可以一次存储两行并使用它们。这样,已用空间将从 L[m+1][n+1] 减少到 L[2][n+1]。下面是上述想法的实现。

C++

// Space optimized C++ implementation
// of LCS problem
#include
using namespace std;
 
// Returns length of LCS
// for X[0..m-1], Y[0..n-1]
int lcs(string &X, string &Y)
{
     
    // Find lengths of two strings
    int m = X.length(), n = Y.length();
 
    int L[2][n + 1];
 
    // Binary index, used to
    // index current row and
    // previous row.
    bool bi;
 
    for (int i = 0; i <= m; i++)
    {
         
        // Compute current
        // binary index
        bi = i & 1;
 
        for (int j = 0; j <= n; j++)
        {
            if (i == 0 || j == 0)
                L[bi][j] = 0;
 
            else if (X[i-1] == Y[j-1])
                 L[bi][j] = L[1 - bi][j - 1] + 1;
 
            else
                L[bi][j] = max(L[1 - bi][j],
                               L[bi][j - 1]);
        }
    }
 
    // Last filled entry contains
    // length of LCS
    // for X[0..n-1] and Y[0..m-1]
    return L[bi][n];
}
 
// Driver code
int main()
{
    string X = "AGGTAB";
    string Y = "GXTXAYB";
 
    printf("Length of LCS is %d\n", lcs(X, Y));
 
    return 0;
}

Java

// Java Code for A Space Optimized
// Solution of LCS
 
class GFG {
     
    // Returns length of LCS
    // for X[0..m - 1],
    // Y[0..n - 1]
    public static int lcs(String X,
                          String Y)
    {
         
        // Find lengths of two strings
        int m = X.length(), n = Y.length();
     
        int L[][] = new int[2][n+1];
     
        // Binary index, used to index
        // current row and previous row.
        int bi=0;
     
        for (int i = 0; i <= m; i++)
        {
             
            // Compute current binary index
            bi = i & 1;
     
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    L[bi][j] = 0;
     
                else if (X.charAt(i - 1) ==
                         Y.charAt(j - 1))
                    L[bi][j] = L[1 - bi][j - 1] + 1;
     
                else
                    L[bi][j] = Math.max(L[1 - bi][j],
                                        L[bi][j - 1]);
            }
        }
     
        // Last filled entry contains length of
        // LCS for X[0..n-1] and Y[0..m-1]
        return L[bi][n];
    }
     
     
    // Driver Code
    public static void main(String[] args)
    {
        String X = "AGGTAB";
        String Y = "GXTXAYB";
     
        System.out.println("Length of LCS is " +
                                    lcs(X, Y));
    }
}
 
// This code is contributed by Arnav Kr. Mandal.

蟒蛇3

# Space optimized Python
# implementation of LCS problem
 
# Returns length of LCS for
# X[0..m-1], Y[0..n-1]
def lcs(X, Y):
     
    # Find lengths of two strings
    m = len(X)
    n = len(Y)
 
    L = [[0 for i in range(n+1)] for j in range(2)]
 
    # Binary index, used to index current row and
    # previous row.
    bi = bool
     
    for i in range(m):
        # Compute current binary index
        bi = i&1
 
        for j in range(n+1):
            if (i == 0 or j == 0):
                L[bi][j] = 0
 
            elif (X[i] == Y[j - 1]):
                L[bi][j] = L[1 - bi][j - 1] + 1
 
            else:
                L[bi][j] = max(L[1 - bi][j],
                               L[bi][j - 1])
 
    # Last filled entry contains length of LCS
    # for X[0..n-1] and Y[0..m-1]
    return L[bi][n]
 
# Driver Code
X = "AGGTAB"
Y = "GXTXAYB"
 
print("Length of LCS is", lcs(X, Y))
 
# This code is contributed by Soumen Ghosh.

C#

// C# Code for A Space
// Optimized Solution of LCS
using System;
 
class GFG
{
     
    // Returns length of LCS
    // for X[0..m - 1],
    // Y[0..n - 1]
    public static int lcs(string X,
                          string Y)
    {
         
        // Find lengths of
        // two strings
        int m = X.Length, n = Y.Length;
     
        int [,]L = new int[2, n + 1];
     
        // Binary index, used to
        // index current row and
        // previous row.
        int bi = 0;
     
        for (int i = 0; i <= m; i++)
        {
             
            // Compute current
            // binary index
            bi = i & 1;
     
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    L[bi, j] = 0;
      
                else if (X[i - 1] == Y[j - 1])
                    L[bi, j] = L[1 - bi,
                                 j - 1] + 1;
     
                else
                    L[bi, j] = Math.Max(L[1 - bi, j],
                                        L[bi, j - 1]);
            }
        }
     
        // Last filled entry contains
        // length of LCS for X[0..n-1]
        // and Y[0..m-1]
        return L[bi, n];
    }
     
    // Driver Code
    public static void Main()
    {
        string X = "AGGTAB";
        string Y = "GXTXAYB";
     
        Console.Write("Length of LCS is " +
                                lcs(X, Y));
    }
}
 
// This code is contributed
// by shiv_bhakt.

PHP


Javascript


输出:

Length of LCS is 4

时间复杂度: O(m*n)
辅助空间: O(n)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程