📜  最长公共子串(空间优化DP方案)

📅  最后修改于: 2021-09-17 16:07:20             🧑  作者: Mango

给定两个字符串“X”和“Y”,求最长公共子串的长度。预期的空间复杂度是线性的。
例子 :

Input : X = "GeeksforGeeks", Y = "GeeksQuiz"
Output : 5
The longest common substring is "Geeks" and is of
length 5.

Input : X = "abcdxyz", Y = "xyzabcd"
Output : 4
The longest common substring is "abcd" and is of
length 4.

最长公共子串

我们已经讨论了基于动态规划的最长公共子串的解决方案。解所使用的辅助空间为O(m*n),其中m和n分别为字符串X和Y的长度。解所使用的空间可以缩减为O(2*n)。
假设我们在位置 mat[i][j]。现在如果 X[i-1] == Y[j-1],那么我们将 mat[i-1][j-1] 的值添加到我们的结果中。也就是说,我们从前一行添加值,并且从不使用前一行下方所有其他行的值。因此,我们一次只使用连续的两行。此观察可用于减少查找最长公共子串长度所需的空间。
我们不是创建一个大小为 m*n 的矩阵,而是创建一个大小为 2*n 的矩阵。变量 currRow 用于表示该矩阵的第 0 行或第 1 行当前用于查找长度。对于字符串X 的长度为零的情况,最初第 0 行用作当前行。在每次迭代结束时,当前行成为前一行,前一行成为新的当前行。

C++
// Space optimized CPP implementation of longest
// common substring.
#include 
using namespace std;
 
// Function to find longest common substring.
int LCSubStr(string X, string Y)
{
    // Find length of both the strings.
    int m = X.length();
    int n = Y.length();
 
    // Variable to store length of longest
    // common substring.
    int result = 0;
 
    // Matrix to store result of two
    // consecutive rows at a time.
    int len[2][n];
 
    // Variable to represent which row of
    // matrix is current row.
    int currRow = 0;
 
    // For a particular value of i and j,
    // len[currRow][j] stores length of longest
    // common substring in string X[0..i] and Y[0..j].
    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (i == 0 || j == 0) {
                len[currRow][j] = 0;
            }
            else if (X[i - 1] == Y[j - 1]) {
                len[currRow][j] = len[1 - currRow][j - 1] + 1;
                result = max(result, len[currRow][j]);
            }
            else {
                len[currRow][j] = 0;
            }
        }
 
        // Make current row as previous row and previous
        // row as new current row.
        currRow = 1 - currRow;
    }
 
    return result;
}
 
int main()
{
    string X = "GeeksforGeeks";
    string Y = "GeeksQuiz";
 
    cout << LCSubStr(X, Y);
    return 0;
}


Java
// Space optimized CPP implementation of
// longest common substring.
import java.io.*;
import java.util.*;
 
public class GFG {
     
    // Function to find longest
    // common substring.
    static int LCSubStr(String X, String Y)
    {
         
        // Find length of both the strings.
        int m = X.length();
        int n = Y.length();
     
        // Variable to store length of longest
        // common substring.
        int result = 0;
     
        // Matrix to store result of two
        // consecutive rows at a time.
        int [][]len = new int[2][n];
     
        // Variable to represent which row of
        // matrix is current row.
        int currRow = 0;
     
        // For a particular value of
        // i and j, len[currRow][j]
        // stores length of longest
        // common substring in string
        // X[0..i] and Y[0..j].
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || j == 0) {
                    len[currRow][j] = 0;
                }
                else if (X.charAt(i - 1) ==
                              Y.charAt(j - 1))
                {
                    len[currRow][j] =
                      len[(1 - currRow)][(j - 1)]
                                             + 1;
                    result = Math.max(result,
                                len[currRow][j]);
                }
                else
                {
                    len[currRow][j] = 0;
                }
            }
     
            // Make current row as previous
            // row and previous row as
            // new current row.
            currRow = 1 - currRow;
        }
     
        return result;
    }
     
    // Driver Code
    public static void main(String args[])
    {
        String X = "GeeksforGeeks";
        String Y = "GeeksQuiz";
     
        System.out.print(LCSubStr(X, Y));
    }
}
 
// This code is contributed by
// Manish Shaw (manishshaw1)


Python3
# Space optimized Python3 implementation 
# of longest common substring.
import numpy as np
 
# Function to find longest common substring.
def LCSubStr(X, Y) :
 
    # Find length of both the strings.
    m = len(X)
    n = len(Y)
 
    # Variable to store length of
    # longest common substring.
    result = 0
 
    # Matrix to store result of two
    # consecutive rows at a time.
    len_mat = np.zeros((2, n))
 
    # Variable to represent which row 
    # of matrix is current row.
    currRow = 0
 
    # For a particular value of i and j,
    # len_mat[currRow][j] stores length of
    # longest common substring in string
    # X[0..i] and Y[0..j].
    for i in range(m) :
        for j in range(n) :
                         
            if (i == 0 | j == 0) :
                len_mat[currRow][j] = 0
             
            elif (X[i - 1] == Y[j - 1]) :
                                 
                len_mat[currRow][j] = len_mat[1 - currRow][j - 1] + 1
                result = max(result, len_mat[currRow][j])
             
            else :
                len_mat[currRow][j] = 0
             
        # Make current row as previous row and
        # previous row as new current row.
        currRow = 1 - currRow
 
    return result
 
# Driver Code
if __name__ == "__main__" :
 
    X = "GeeksforGeeks"
    Y = "GeeksQuiz"
 
    print(LCSubStr(X, Y))
 
# This code is contributed by Ryuga


C#
// Space optimized C# implementation
// of longest common substring.
using System;
using System.Collections.Generic;
class GFG {
     
    // Function to find longest
    // common substring.
    static int LCSubStr(string X, string Y)
    {
         
        // Find length of both the strings.
        int m = X.Length;
        int n = Y.Length;
     
        // Variable to store length of longest
        // common substring.
        int result = 0;
     
        // Matrix to store result of two
        // consecutive rows at a time.
        int [,]len = new int[2,n];
     
        // Variable to represent which row of
        // matrix is current row.
        int currRow = 0;
     
        // For a particular value of
        // i and j, len[currRow][j]
        // stores length of longest
        // common substring in string
        // X[0..i] and Y[0..j].
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || j == 0) {
                    len[currRow,j] = 0;
                }
                else if (X[i - 1] == Y[j - 1]) {
                    len[currRow,j] = len[(1 - currRow),
                                          (j - 1)] + 1;
                    result = Math.Max(result, len[currRow, j]);
                }
                else
                {
                    len[currRow,j] = 0;
                }
            }
     
            // Make current row as previous
            // row and previous row as
            // new current row.
            currRow = 1 - currRow;
        }
     
        return result;
    }
     
     
    // Driver Code
    public static void Main()
    {
        string X = "GeeksforGeeks";
        string Y = "GeeksQuiz";
     
        Console.Write(LCSubStr(X, Y));
    }
}
 
// This code is contributed by
// Manish Shaw (manishshaw1)


PHP


Javascript


输出 :
5

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

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