Given two strings ‘X’ and ‘Y’, find the length of longest common substring. Expected space complexity is linear.
Examples :
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.

We have discussed Dynamic programming based solution for Longest common substring. The auxiliary space used by the solution is O(m*n), where m and n are lengths of string X and Y. The space used by solution can be reduced to O(2*n).
Suppose we are at position mat[i][j]. Now if X[i-1] == Y[j-1], then we add the value of mat[i-1][j-1] to our result. That is we add value from previous row and value for all other rows below the previous row are never used. So, at a time we are using only two consecutive rows. This observation can be used to reduce the space required to find length of longest common substring.
Instead of creating a matrix of size m*n, we create a matrix of size 2*n. A variable currRow is used to represent that either row 0 or row 1 of this matrix is currently used to find length. Initially row 0 is used as current row for the case when length of string X is zero. At the end of each iteration, current row is made previous row and previous row is made new current row.
C++
#include <bits/stdc++.h>
using namespace std;
int LCSubStr(string X, string Y)
{
int m = X.length();
int n = Y.length();
int result = 0;
int len[2][n];
int currRow = 0;
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;
}
}
currRow = 1 - currRow;
}
return result;
}
int main()
{
string X = "GeeksforGeeks" ;
string Y = "GeeksQuiz" ;
cout << LCSubStr(X, Y);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
public class GFG {
static int LCSubStr(String X, String Y)
{
int m = X.length();
int n = Y.length();
int result = 0 ;
int [][]len = new int [ 2 ][n];
int currRow = 0 ;
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 ;
}
}
currRow = 1 - currRow;
}
return result;
}
public static void main(String args[])
{
String X = "GeeksforGeeks" ;
String Y = "GeeksQuiz" ;
System.out.print(LCSubStr(X, Y));
}
}
|
Python3
import numpy as np
def LCSubStr(X, Y) :
m = len (X)
n = len (Y)
result = 0
len_mat = np.zeros(( 2 , n))
currRow = 0
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
currRow = 1 - currRow
return result
if __name__ = = "__main__" :
X = "GeeksforGeeks"
Y = "GeeksQuiz"
print (LCSubStr(X, Y))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int LCSubStr( string X, string Y)
{
int m = X.Length;
int n = Y.Length;
int result = 0;
int [,]len = new int [2,n];
int currRow = 0;
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;
}
}
currRow = 1 - currRow;
}
return result;
}
public static void Main()
{
string X = "GeeksforGeeks" ;
string Y = "GeeksQuiz" ;
Console.Write(LCSubStr(X, Y));
}
}
|
PHP
<?php
function LCSubStr( $X , $Y )
{
$m = strlen ( $X );
$n = strlen ( $Y );
$result = 0;
$len = array ( array (), array (), );
$currRow = 0;
for ( $i = 0; $i <= $m ; $i ++)
{
for ( $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;
}
}
$currRow = 1 - $currRow ;
}
return $result ;
}
$X = "GeeksforGeeks" ;
$Y = "GeeksQuiz" ;
print (LCSubStr( $X , $Y ));
?>
|
Javascript
<script>
function LCSubStr(X, Y)
{
var m = X.length;
var n = Y.length;
var result = 0;
var len = Array.from(Array(2), ()=> Array(n));
var currRow = 0;
for ( var i = 0; i <= m; i++) {
for ( var 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;
}
}
currRow = 1 - currRow;
}
return result;
}
var X = "GeeksforGeeks" ;
var Y = "GeeksQuiz" ;
document.write( LCSubStr(X, Y));
</script>
|
Time Complexity: O(m*n)
Auxiliary Space: O(n)