Print the longest common substring
Last Updated :
15 Jul, 2022
Given two strings ‘X’ and ‘Y’, print the length of the longest common substring. If two or more substrings have the same value for the longest common substring, then print any one of them.
Examples:
Input : X = "GeeksforGeeks",
Y = "GeeksQuiz"
Output : Geeks
Input : X = "zxabcdezy",
Y = "yzabcdezx"
Output : abcdez
We have discussed a solution to find the length of the longest common string. In this post, we have discussed printing common string is discussed.
Naive Approach: Let strings X and Y be the lengths m and n respectively. Generate all possible substrings of X which requires a time complexity of O(m2) and search each substring in the string Y which can be achieved in O(n) time complexity using the KMP algorithm. Overall time complexity will be O(n * m2).
Efficient Approach: It is based on the dynamic programming implementation explained in this post. The longest suffix matrix LCSuff[][] is build up and the index of the cell having the maximum value is tracked. Let that index be represented by (row, col) pair. Now the final longest common substring is built with the help of that index by diagonally traversing up the LCSuff[][] matrix until LCSuff[row][col] != 0 and during the iteration obtaining the characters either from X[row-1] or Y[col-1] and adding them from right to left in the resultant common string.
Implementation:
C++
// C++ implementation to print the longest common substring
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
/* function to find and print the longest common
substring of X[0..m-1] and Y[0..n-1] */
void printLCSubStr(char* X, char* Y, int m, int n)
{
// Create a table to store lengths of longest common
// suffixes of substrings. Note that LCSuff[i][j]
// contains length of longest common suffix of X[0..i-1]
// and Y[0..j-1]. The first row and first column entries
// have no logical meaning, they are used only for
// simplicity of program
int LCSuff[m + 1][n + 1];
// To store length of the longest common substring
int len = 0;
// To store the index of the cell which contains the
// maximum value. This cell's index helps in building
// up the longest common substring from right to left.
int row, col;
/* Following steps build LCSuff[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)
LCSuff[i][j] = 0;
else if (X[i - 1] == Y[j - 1]) {
LCSuff[i][j] = LCSuff[i - 1][j - 1] + 1;
if (len < LCSuff[i][j]) {
len = LCSuff[i][j];
row = i;
col = j;
}
}
else
LCSuff[i][j] = 0;
}
}
// if true, then no common substring exists
if (len == 0) {
cout << "No Common Substring";
return;
}
// allocate space for the longest common substring
char* resultStr = (char*)malloc((len + 1) * sizeof(char));
// traverse up diagonally form the (row, col) cell
// until LCSuff[row][col] != 0
while (LCSuff[row][col] != 0) {
resultStr[--len] = X[row - 1]; // or Y[col-1]
// move diagonally up to previous cell
row--;
col--;
}
// required longest common substring
cout << resultStr;
}
/* Driver program to test above function */
int main()
{
char X[] = "OldSite:GeeksforGeeks.org";
char Y[] = "NewSite:GeeksQuiz.com";
int m = strlen(X);
int n = strlen(Y);
printLCSubStr(X, Y, m, n);
return 0;
}
Java
// Java implementation to print the longest common substring
public class Longest_common_substr {
/* function to find and print the longest common
substring of X[0..m-1] and Y[0..n-1] */
static void printLCSubStr(String X, String Y, int m, int n)
{
// Create a table to store lengths of longest common
// suffixes of substrings. Note that LCSuff[i][j]
// contains length of longest common suffix of X[0..i-1]
// and Y[0..j-1]. The first row and first column entries
// have no logical meaning, they are used only for
// simplicity of program
int[][] LCSuff = new int[m + 1][n + 1];
// To store length of the longest common substring
int len = 0;
// To store the index of the cell which contains the
// maximum value. This cell's index helps in building
// up the longest common substring from right to left.
int row = 0, col = 0;
/* Following steps build LCSuff[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)
LCSuff[i][j] = 0;
else if (X.charAt(i - 1) == Y.charAt(j - 1)) {
LCSuff[i][j] = LCSuff[i - 1][j - 1] + 1;
if (len < LCSuff[i][j]) {
len = LCSuff[i][j];
row = i;
col = j;
}
}
else
LCSuff[i][j] = 0;
}
}
// if true, then no common substring exists
if (len == 0) {
System.out.println("No Common Substring");
return;
}
// allocate space for the longest common substring
String resultStr = "";
// traverse up diagonally form the (row, col) cell
// until LCSuff[row][col] != 0
while (LCSuff[row][col] != 0) {
resultStr = X.charAt(row - 1) + resultStr; // or Y[col-1]
--len;
// move diagonally up to previous cell
row--;
col--;
}
// required longest common substring
System.out.println(resultStr);
}
/* Driver program to test above function */
public static void main(String args[])
{
String X = "OldSite:GeeksforGeeks.org";
String Y = "NewSite:GeeksQuiz.com";
int m = X.length();
int n = Y.length();
printLCSubStr(X, Y, m, n);
}
}
// This code is contributed by Sumit Ghosh
Python3
# Python3 implementation to print
# the longest common substring
# function to find and print
# the longest common substring of
# X[0..m-1] and Y[0..n-1]
def printLCSSubStr(X: str, Y: str,
m: int, n: int):
# Create a table to store lengths of
# longest common suffixes of substrings.
# Note that LCSuff[i][j] contains length
# of longest common suffix of X[0..i-1] and
# Y[0..j-1]. The first row and first
# column entries have no logical meaning,
# they are used only for simplicity of program
LCSuff = [[0 for i in range(n + 1)]
for j in range(m + 1)]
# To store length of the
# longest common substring
length = 0
# To store the index of the cell
# which contains the maximum value.
# This cell's index helps in building
# up the longest common substring
# from right to left.
row, col = 0, 0
# Following steps build LCSuff[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:
LCSuff[i][j] = 0
else if X[i - 1] == Y[j - 1]:
LCSuff[i][j] = LCSuff[i - 1][j - 1] + 1
if length < LCSuff[i][j]:
length = LCSuff[i][j]
row = i
col = j
else:
LCSuff[i][j] = 0
# if true, then no common substring exists
if length == 0:
print("No Common Substring")
return
# allocate space for the longest
# common substring
resultStr = ['0'] * length
# traverse up diagonally form the
# (row, col) cell until LCSuff[row][col] != 0
while LCSuff[row][col] != 0:
length -= 1
resultStr[length] = X[row - 1] # or Y[col-1]
# move diagonally up to previous cell
row -= 1
col -= 1
# required longest common substring
print(''.join(resultStr))
# Driver Code
if __name__ == "__main__":
X = "OldSite:GeeksforGeeks.org"
Y = "NewSite:GeeksQuiz.com"
m = len(X)
n = len(Y)
printLCSSubStr(X, Y, m, n)
# This code is contributed by
# sanjeev2552
C#
// C# implementation to print the
// longest common substring
using System;
class GFG {
/* function to find and print the longest common
substring of X[0..m-1] and Y[0..n-1] */
static void printLCSubStr(String X, String Y, int m, int n)
{
// Create a table to store lengths of longest common
// suffixes of substrings. Note that LCSuff[i][j]
// contains length of longest common suffix of X[0..i-1]
// and Y[0..j-1]. The first row and first column entries
// have no logical meaning, they are used only for
// simplicity of program
int[, ] LCSuff = new int[m + 1, n + 1];
// To store length of the longest common substring
int len = 0;
// To store the index of the cell which contains the
// maximum value. This cell's index helps in building
// up the longest common substring from right to left.
int row = 0, col = 0;
/* Following steps build LCSuff[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)
LCSuff[i, j] = 0;
else if (X[i - 1] == Y[j - 1]) {
LCSuff[i, j] = LCSuff[i - 1, j - 1] + 1;
if (len < LCSuff[i, j]) {
len = LCSuff[i, j];
row = i;
col = j;
}
}
else
LCSuff[i, j] = 0;
}
}
// if true, then no common substring exists
if (len == 0) {
Console.Write("No Common Substring");
return;
}
// allocate space for the longest common substring
String resultStr = "";
// traverse up diagonally form the (row, col) cell
// until LCSuff[row][col] != 0
while (LCSuff[row, col] != 0) {
resultStr = X[row - 1] + resultStr; // or Y[col-1]
--len;
// move diagonally up to previous cell
row--;
col--;
}
// required longest common substring
Console.WriteLine(resultStr);
}
/* Driver program to test above function */
public static void Main()
{
String X = "OldSite:GeeksforGeeks.org";
String Y = "NewSite:GeeksQuiz.com";
int m = X.Length;
int n = Y.Length;
printLCSubStr(X, Y, m, n);
}
}
// This code is contributed by Sam007
JavaScript
<script>
// Javascript implementation to print the longest common substring
/* function to find and print the longest common
substring of X[0..m-1] and Y[0..n-1] */
function printLCSubStr(X,Y,m,n)
{
// Create a table to store lengths of longest common
// suffixes of substrings. Note that LCSuff[i][j]
// contains length of longest common suffix of X[0..i-1]
// and Y[0..j-1]. The first row and first column entries
// have no logical meaning, they are used only for
// simplicity of program
let LCSuff = new Array(m+1);
// To store length of the longest common substring
let len = 0;
// To store the index of the cell which contains the
// maximum value. This cell's index helps in building
// up the longest common substring from right to left.
let row = 0, col = 0;
/* Following steps build LCSuff[m+1][n+1] in bottom
up fashion. */
for (let i = 0; i <= m; i++) {
LCSuff[i] = Array(n+1);
for (let j = 0; j <= n; j++) {
LCSuff[i][j]=0;
if (i == 0 || j == 0)
LCSuff[i][j] = 0;
else if (X[i-1] == Y[j-1]) {
LCSuff[i][j] = LCSuff[i - 1][j - 1] + 1;
if (len < LCSuff[i][j]) {
len = LCSuff[i][j];
row = i;
col = j;
}
}
else
LCSuff[i][j] = 0;
}
}
// if true, then no common substring exists
if (len == 0) {
document.write("No Common Substring");
return;
}
// allocate space for the longest common substring
let resultStr = "";
// traverse up diagonally form the (row, col) cell
// until LCSuff[row][col] != 0
while (LCSuff[row][col] != 0) {
resultStr = X[row-1] + resultStr; // or Y[col-1]
--len;
// move diagonally up to previous cell
row--;
col--;
}
// required longest common substring
document.write(resultStr);
}
/* Driver program to test above function */
let X = "OldSite:GeeksforGeeks.org";
let Y = "NewSite:GeeksQuiz.com";
let m = X.length;
let n = Y.length;
printLCSubStr(X, Y, m, n);
//This code is contributed by rag2127
</script>
Time Complexity: O(m*n).
Auxiliary Space: O(m*n).
Space Optimized Approach: The auxiliary space used by the solution above is O(m*n), where m and n are lengths of string X and Y. The space used by the above solution can be reduced to O(2*n). A variable end is used to store the ending point of the longest common substring in string X and variable maxlen is used to store the length of the longest common substring.
Suppose we are at DP state when the length of X is i and length of Y is j, the result of which is stored in len[i][j].
Now if X[i-1] == Y[j-1], then len[i][j] = 1 + len[i-1][j-1], that is result of current row in matrix len[][] depends on values from previous row. Hence, the required length of the longest common substring can be obtained by maintaining values of two consecutive rows only, thereby reducing space requirements to O(2*n).
To print the longest common substring, we use a variable end. When len[i][j] is calculated, it is compared with maxlen. If maxlen is less than len[i][j], then end is updated to i-1 to show that longest common substring ends at index i-1 in X and maxlen is updated to len[i][j]. The longest common substring then is from index end - maxlen + 1 to index end in X.
A variable currRow is used to represent that either row 0 or row 1 of len[2][n] matrix is currently used to find the length. Initially, row 0 is used as the current row for the case when the length of string X is zero. At the end of each iteration, the current row is made the previous row and the previous row is made the new current row.
Given below is the implementation of the above approach:
C++
// Space optimized CPP implementation to print
// longest common substring.
#include <bits/stdc++.h>
using namespace std;
// Function to find longest common substring.
string 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;
// Variable to store ending point of
// longest common substring in X.
int end;
// Matrix to store result of two
// consecutive rows at a time.
int len[2][n + 1];
// 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;
if (len[currRow][j] > result) {
result = len[currRow][j];
end = i - 1;
}
}
else {
len[currRow][j] = 0;
}
}
// Make current row as previous row and
// previous row as new current row.
currRow = 1 - currRow;
}
// If there is no common substring, print -1.
if (result == 0) {
return "-1";
}
// Longest common substring is from index
// end - result + 1 to index end in X.
return X.substr(end - result + 1, result);
}
// Driver Code
int main()
{
string X = "GeeksforGeeks";
string Y = "GeeksQuiz";
// function call
cout << LCSubStr(X, Y);
return 0;
}
Java
// Space optimized Java implementation to print
// longest common substring.
public class GFG {
// Function to find longest common substring.
static String 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;
// Variable to store ending point of
// longest common subString in X.
int end = 0;
// Matrix to store result of two
// consecutive rows at a time.
int len[][] = new int[2][m];
// 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;
if (len[currRow][j] > result) {
result = len[currRow][j];
end = i - 1;
}
} else {
len[currRow][j] = 0;
}
}
// Make current row as previous row and
// previous row as new current row.
currRow = 1 - currRow;
}
// If there is no common subString, print -1.
if (result == 0) {
return "-1";
}
// Longest common subString is from index
// end - result + 1 to index end in X.
return X.substring(end - result + 1, result);
}
// Driver Code
public static void main(String[] args) {
String X = "GeeksforGeeks";
String Y = "GeeksQuiz";
// function call
System.out.println(LCSubStr(X, Y));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Space optimized Python3 implementation to
# print longest common substring.
# 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
# Variable to store ending point of
# longest common substring in X.
end = 0
# Matrix to store result of two
# consecutive rows at a time.
length = [[0 for j in range(m)]
for i in range(2)]
# Variable to represent which row of
# matrix is current row.
currRow = 0
# For a particular value of i and j,
# length[currRow][j] stores length
# of longest common substring in
# string X[0..i] and Y[0..j].
for i in range(0, m + 1):
for j in range(0, n + 1):
if (i == 0 or j == 0):
length[currRow][j] = 0
elif (X[i - 1] == Y[j - 1]):
length[currRow][j] = length[1 - currRow][j - 1] + 1
if (length[currRow][j] > result):
result = length[currRow][j]
end = i - 1
else:
length[currRow][j] = 0
# Make current row as previous row and
# previous row as new current row.
currRow = 1 - currRow
# If there is no common substring, print -1.
if (result == 0):
return "-1"
# Longest common substring is from index
# end - result + 1 to index end in X.
return X[end - result + 1 : end + 1]
# Driver code
if __name__=="__main__":
X = "GeeksforGeeks"
Y = "GeeksQuiz"
# Function call
print(LCSubStr(X, Y))
# This code is contributed by rutvik_56
C#
using System;
// Space optimized Java implementation to print
// longest common substring.
public class GFG {
// Function to find longest common substring.
static string 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;
// Variable to store ending point of
// longest common subString in X.
int end = 0;
// Matrix to store result of two
// consecutive rows at a time.
int[,] len = new int[2,m];
// 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;
if (len[currRow,j] > result) {
result = len[currRow,j];
end = i - 1;
}
} else {
len[currRow,j] = 0;
}
}
// Make current row as previous row and
// previous row as new current row.
currRow = 1 - currRow;
}
// If there is no common subString, print -1.
if (result == 0) {
return "-1";
}
// Longest common subString is from index
// end - result + 1 to index end in X.
return X.Substring(end - result + 1, result);
}
// Driver Code
public static void Main() {
string X = "GeeksforGeeks";
string Y = "GeeksQuiz";
// function call
Console.Write(LCSubStr(X, Y));
}
}
JavaScript
<script>
// Space optimized javascript implementation to print
// longest common substring.
// Function to find longest common substring.
function LCSubStr(X,Y)
{
// Find length of both the strings.
let m = X.length;
let n = Y.length;
// Variable to store length of longest
// common substring.
let result = 0;
// Variable to store ending point of
// longest common substring in X.
let end;
// Matrix to store result of two
// consecutive rows at a time.
let len= new Array(2);
for(let i=0;i<len.length;i++)
{
len[i]=new Array(n);
for(let j=0;j<n;j++)
{
len[i][j]=0;
}
}
// Variable to represent which row of
// matrix is current row.
let 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 (let i = 0; i <= m; i++) {
for (let 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;
if (len[currRow][j] > result) {
result = len[currRow][j];
end = i - 1;
}
}
else {
len[currRow][j] = 0;
}
}
// Make current row as previous row and
// previous row as new current row.
currRow = 1 - currRow;
}
// If there is no common substring, print -1.
if (result == 0) {
return "-1";
}
// Longest common substring is from index
// end - result + 1 to index end in X.
return X.substr(end - result + 1, result);
}
// Driver Code
let X = "GeeksforGeeks";
let Y = "GeeksQuiz";
// function call
document.write(LCSubStr(X, Y));
// This code is contributed by avanitrachhadiya2155
</script>
Time Complexity: O(m*n)
Auxiliary Space: O(n)
This approach has been suggested by nik1996.
Similar Reads
Longest Common Substring
Given two strings 's1' and 's2', find the length of the longest common substring. Example: Input: s1 = "GeeksforGeeks", s2 = "GeeksQuiz" Output : 5 Explanation:The longest common substring is "Geeks" and is of length 5.Input: s1 = "abcdxyz", s2 = "xyzabcd" Output : 4Explanation:The longest common su
15+ min read
Longest Common Substring with max XOR
Given two strings s1 and s2, the task is to find the length of the longest common substring of s1 and s2 such that the XOR is maximum. Examples: Input: s1 = "79567", s2 = "56779"Output: 2Explanation: The longest common substring with a max XOR is "79", which has an XOR of 14 and a length is 2. Input
8 min read
Printing Longest Common Subsequence
Given two sequences, print the longest subsequence present in both of them. Examples: LCS for input Sequences âABCDGHâ and âAEDFHRâ is âADHâ of length 3. LCS for input Sequences âAGGTABâ and âGXTXAYBâ is âGTABâ of length 4.We have discussed Longest Common Subsequence (LCS) problem in a previous post
15+ min read
Find the Longest Substring Conversion
Given two strings source and target of equal length, and two positive integers, maxCost, and conversionCost, the task is to find the indices of the longest substring in source that can be converted into the same substring in target with a cost less than or equal to maxCost, where each character conv
12 min read
Longest Common Prefix using Sorting
Given an array of strings arr[], the task is to return the longest common prefix among each and every strings present in the array. If thereâs no prefix common in all the strings, return ââ.Examples:Input: arr[] = [âgeeksforgeeksâ, âgeeksâ, âgeekâ, âgeezerâ]Output: âgeeâExplanation: âgeeâ is the lon
5 min read
LCS (Longest Common Subsequence) of three strings
Given 3 strings say s1, s2 and s3. The task is to find the longest common sub-sequence in all three given sequences.Examples: Input: s1 = "geeks" , s2 = "geeksfor", s3 = "geeksforgeeks"Output : 5Explanation: Longest common subsequence is "geeks" i.e., length = 5Input: s1= "abcd1e2" , s2= "bc12ea" ,
15+ min read
Longest Common Substring in an Array of Strings
We are given a list of words sharing a common stem i.e the words originate from same word for ex: the words sadness, sadly and sad all originate from the stem 'sad'. Our task is to find and return the Longest Common Substring also known as stem of those words. In case there are ties, we choose the s
7 min read
Find the longest Substring of a given String S
Given a string S of length, N. Find the maximum length of any substring of S such that, the bitwise OR of all the characters of the substring is equal to the bitwise OR of the remaining characters of the string. If no such substring exists, print -1. Examples: Input: S = "2347"Output: 3?Explanation:
10 min read
Longest Common Prefix using Binary Search
Given an array of strings arr[], the task is to return the longest common prefix among each and every strings present in the array. If thereâs no prefix common in all the strings, return "".Examples:Input: arr[] = [âgeeksforgeeksâ, âgeeksâ, âgeekâ, âgeezerâ]Output: "gee"Explanation: "gee" is the lon
8 min read
Longest Palindromic Substring
Given a string s, the task is to find the longest substring which is a palindrome. If there are multiple answers, then return the first appearing substring.Examples:Input: s = "forgeeksskeegfor" Output: "geeksskeeg"Explanation: There are several possible palindromic substrings like "kssk", "ss", "ee
12 min read