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

📅  最后修改于: 2021-05-04 20:45:36             🧑  作者: 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


输出 :
5

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