Given two strings str1 and str2, the task is to find the length of the shortest string that has both str1 and str2 as subsequences.
Examples :
Input: str1 = "geek", str2 = "eke"
Output: 5
Explanation:
String "geeke" has both string "geek"
and "eke" as subsequences.
Input: str1 = "AGGTAB", str2 = "GXTXAYB"
Output: 9
Explanation:
String "AGXGTXAYB" has both string
"AGGTAB" and "GXTXAYB" as subsequences.
Method 1: This problem is closely related to longest common subsequence problem.
Below are steps.
- Find Longest Common Subsequence (lcs) of two given strings. For example, lcs of “geek” and “eke” is “ek”.
- Insert non-lcs characters (in their original order in strings) to the lcs found above, and return the result. So “ek” becomes “geeke” which is shortest common supersequence.
Let us consider another example, str1 = “AGGTAB” and str2 = “GXTXAYB”. LCS of str1 and str2 is “GTAB”. Once we find LCS, we insert characters of both strings in order and we get “AGXGTXAYB”
How does this work?
We need to find a string that has both strings as subsequences and is the shortest such string. If both strings have all characters different, then result is sum of lengths of two given strings. If there are common characters, then we don’t want them multiple times as the task is to minimize length. Therefore, we first find the longest common subsequence, take one occurrence of this subsequence and add extra characters.
Length of the shortest supersequence
= (Sum of lengths of given two strings)
- (Length of LCS of two given strings)
Below is the implementation of above idea. The below implementation only finds length of the shortest super sequence.
C++
#include <bits/stdc++.h>
using namespace std;
int max( int a, int b) { return (a > b) ? a : b; }
int lcs( char * X, char * Y, int m, int n);
int shortestSuperSequence( char * X, char * Y)
{
int m = strlen (X), n = strlen (Y);
int l = lcs(X, Y, m, n);
return (m + n - l);
}
int lcs( char * X, char * Y, int m, int n)
{
int L[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (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]);
}
}
return L[m][n];
}
int main()
{
char X[] = "AGGTAB" ;
char Y[] = "GXTXAYB" ;
cout << "Length of the shortest supersequence is "
<< shortestSuperSequence(X, Y) << endl;
return 0;
}
|
C
#include <stdio.h>
#include <string.h>
int max( int a, int b) { return (a > b) ? a : b; }
int lcs( char * X, char * Y, int m, int n);
int shortestSuperSequence( char * X, char * Y)
{
int m = strlen (X), n = strlen (Y);
int l = lcs(X, Y, m, n);
return (m + n - l);
}
int lcs( char * X, char * Y, int m, int n)
{
int L[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (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]);
}
}
return L[m][n];
}
int main()
{
char X[] = "AGGTAB" ;
char Y[] = "GXTXAYB" ;
printf ( "Length of the shortest supersequence is %d\n" ,
shortestSuperSequence(X, Y));
return 0;
}
|
Java
import java.io.*;
class GFG {
static int shortestSuperSequence(String X, String Y)
{
int m = X.length();
int n = Y.length();
int l = lcs(X, Y, m, n);
return (m + n - l);
}
static int lcs(String X, String Y, int m, int n)
{
int [][] L = new int [m + 1 ][n + 1 ];
int i, j;
for (i = 0 ; i <= m; i++) {
for (j = 0 ; j <= n; j++) {
if (i == 0 || j == 0 )
L[i][j] = 0 ;
else if (X.charAt(i - 1 ) == Y.charAt(j - 1 ))
L[i][j] = L[i - 1 ][j - 1 ] + 1 ;
else
L[i][j] = Math.max(L[i - 1 ][j],
L[i][j - 1 ]);
}
}
return L[m][n];
}
public static void main(String args[])
{
String X = "AGGTAB" ;
String Y = "GXTXAYB" ;
System.out.println( "Length of the shortest "
+ "supersequence is "
+ shortestSuperSequence(X, Y));
}
}
|
Python3
def shortestSuperSequence(X, Y):
m = len (X)
n = len (Y)
l = lcs(X, Y, m, n)
return (m + n - l)
def lcs(X, Y, m, n):
L = [[ 0 ] * (n + 2 ) for i in
range (m + 2 )]
for i in range (m + 1 ):
for j in range (n + 1 ):
if (i = = 0 or j = = 0 ):
L[i][j] = 0
elif (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 ])
return L[m][n]
X = "AGGTAB"
Y = "GXTXAYB"
print ( "Length of the shortest supersequence is %d"
% shortestSuperSequence(X, Y))
|
C#
using System;
class GFG {
static int shortestSuperSequence(String X, String Y)
{
int m = X.Length;
int n = Y.Length;
int l = lcs(X, Y, m, n);
return (m + n - l);
}
static int lcs(String X, String Y, int m, int n)
{
int [, ] L = new int [m + 1, n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (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] = Math.Max(L[i - 1, j],
L[i, j - 1]);
}
}
return L[m, n];
}
public static void Main()
{
String X = "AGGTAB" ;
String Y = "GXTXAYB" ;
Console.WriteLine( "Length of the shortest"
+ "supersequence is "
+ shortestSuperSequence(X, Y));
}
}
|
PHP
<?php
function shortestSuperSequence( $X , $Y )
{
$m = strlen ( $X );
$n = strlen ( $Y );
$l = lcs( $X , $Y , $m , $n );
return ( $m + $n - $l );
}
function lcs( $X , $Y , $m , $n )
{
$L = array_fill (0, $m + 1, array_fill (0, $n + 1, 0));
for ( $i = 0; $i <= $m ; $i ++)
{
for ( $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]);
}
}
return $L [ $m ][ $n ];
}
$X = "AGGTAB" ;
$Y = "GXTXAYB" ;
echo "Length of the shortest supersequence is " .
shortestSuperSequence( $X , $Y ). "\n" ;
?>
|
Javascript
<script>
function shortestSuperSequence(X, Y)
{
var m = X.length;
var n = Y.length;
var l = lcs(X, Y, m, n);
return (m + n - l);
}
function lcs(X, Y , m , n)
{
var L = Array(m+1).fill(0).map(x => Array(n+1).fill(0));
var i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i][j] = 0;
else if (X.charAt(i - 1) == Y.charAt(j - 1))
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = Math.max(L[i - 1][j],
L[i][j - 1]);
}
}
return L[m][n];
}
var X = "AGGTAB" ;
var Y = "GXTXAYB" ;
document.write( "Length of the shortest "
+ "supersequence is "
+ shortestSuperSequence(X, Y));
</script>
|
Output
Length of the shortest supersequence is 9
Time Complexity: O(m*n).
Auxiliary Space: O(m*n)
Method 2: A simple analysis yields below simple recursive solution.
Let X[0..m - 1] and Y[0..n - 1] be two
strings and m and n be respective
lengths.
if (m == 0) return n;
if (n == 0) return m;
// If last characters are same, then
// add 1 to result and
// recur for X[]
if (X[m - 1] == Y[n - 1])
return 1 + SCS(X, Y, m - 1, n - 1);
// Else find shortest of following two
// a) Remove last character from X and recur
// b) Remove last character from Y and recur
else
return 1 + min( SCS(X, Y, m - 1, n), SCS(X, Y, m, n - 1) );
Below is simple naive recursive solution based on above recursive formula.
C++
#include <bits/stdc++.h>
using namespace std;
int superSeq( char * X, char * Y, int m, int n)
{
if (!m)
return n;
if (!n)
return m;
if (X[m - 1] == Y[n - 1])
return 1 + superSeq(X, Y, m - 1, n - 1);
return 1
+ min(superSeq(X, Y, m - 1, n),
superSeq(X, Y, m, n - 1));
}
int main()
{
char X[] = "AGGTAB" ;
char Y[] = "GXTXAYB" ;
cout << "Length of the shortest supersequence is "
<< superSeq(X, Y, strlen (X), strlen (Y));
return 0;
}
|
Java
import java.io.*;
class GFG {
static int superSeq(String X, String Y, int m, int n)
{
if (m == 0 )
return n;
if (n == 0 )
return m;
if (X.charAt(m - 1 ) == Y.charAt(n - 1 ))
return 1 + superSeq(X, Y, m - 1 , n - 1 );
return 1
+ Math.min(superSeq(X, Y, m - 1 , n),
superSeq(X, Y, m, n - 1 ));
}
public static void main(String args[])
{
String X = "AGGTAB" ;
String Y = "GXTXAYB" ;
System.out.println(
"Length of the shortest"
+ "supersequence is: "
+ superSeq(X, Y, X.length(), Y.length()));
}
}
|
Python3
def superSeq(X, Y, m, n):
if ( not m):
return n
if ( not n):
return m
if (X[m - 1 ] = = Y[n - 1 ]):
return 1 + superSeq(X, Y, m - 1 , n - 1 )
return 1 + min (superSeq(X, Y, m - 1 , n),
superSeq(X, Y, m, n - 1 ))
X = "AGGTAB"
Y = "GXTXAYB"
print ( "Length of the shortest supersequence is %d"
% superSeq(X, Y, len (X), len (Y)))
|
C#
using System;
class GFG {
static int superSeq(String X, String Y, int m, int n)
{
if (m == 0)
return n;
if (n == 0)
return m;
if (X[m - 1] == Y[n - 1])
return 1 + superSeq(X, Y, m - 1, n - 1);
return 1
+ Math.Min(superSeq(X, Y, m - 1, n),
superSeq(X, Y, m, n - 1));
}
public static void Main()
{
String X = "AGGTAB" ;
String Y = "GXTXAYB" ;
Console.WriteLine(
"Length of the shortest supersequence is: "
+ superSeq(X, Y, X.Length, Y.Length));
}
}
|
PHP
<?php
function superSeq( $X , $Y , $m , $n )
{
if (! $m )
return $n ;
if (! $n )
return $m ;
if ( $X [ $m - 1] == $Y [ $n - 1])
return 1 + superSeq( $X , $Y , $m - 1, $n - 1);
return 1 + min(superSeq( $X , $Y , $m - 1, $n ),
superSeq( $X , $Y , $m , $n - 1));
}
$X = "AGGTAB" ;
$Y = "GXTXAYB" ;
echo "Length of the shortest supersequence is " ,
superSeq( $X , $Y , strlen ( $X ), strlen ( $Y ));
?>
|
Javascript
<script>
function superSeq(X, Y , m , n)
{
if (m == 0)
return n;
if (n == 0)
return m;
if (X.charAt(m - 1) == Y.charAt(n - 1))
return 1 + superSeq(X, Y, m - 1, n - 1);
return 1
+ Math.min(superSeq(X, Y, m - 1, n),
superSeq(X, Y, m, n - 1));
}
var X = "AGGTAB" ;
var Y = "GXTXAYB" ;
document.write(
"Length of the shortest"
+ "supersequence is "
+ superSeq(X, Y, X.length, Y.length));
</script>
|
Output
Length of the shortest supersequence is 9
Time Complexity: O(2min(m, n)). Since there are overlapping subproblems,
Auxiliary Space: O(min(m, n)), due to recursive call stack
Method 3: We can efficiently solve this recursive problem using Dynamic Programming.
Below is the Dynamic Programming-based implementation.
C++
#include <bits/stdc++.h>
using namespace std;
int superSeq( char * X, char * Y, int m, int n)
{
int dp[m + 1][n + 1];
for ( int i = 0; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
if (!i)
dp[i][j] = j;
else if (!j)
dp[i][j] = i;
else if (X[i - 1] == Y[j - 1])
dp[i][j] = 1 + dp[i - 1][j - 1];
else
dp[i][j]
= 1 + min(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[m][n];
}
int main()
{
char X[] = "AGGTAB" ;
char Y[] = "GXTXAYB" ;
cout << "Length of the shortest supersequence is "
<< superSeq(X, Y, strlen (X), strlen (Y));
return 0;
}
|
Java
import java.io.*;
class GFG {
static int superSeq(String X, String Y, int m, int n)
{
int [][] dp = new int [m + 1 ][n + 1 ];
for ( int i = 0 ; i <= m; i++) {
for ( int j = 0 ; j <= n; j++) {
if (i == 0 )
dp[i][j] = j;
else if (j == 0 )
dp[i][j] = i;
else if (X.charAt(i - 1 ) == Y.charAt(j - 1 ))
dp[i][j] = 1 + dp[i - 1 ][j - 1 ];
else
dp[i][j] = 1
+ Math.min(dp[i - 1 ][j],
dp[i][j - 1 ]);
}
}
return dp[m][n];
}
public static void main(String args[])
{
String X = "AGGTAB" ;
String Y = "GXTXAYB" ;
System.out.println(
"Length of the shortest supersequence is "
+ superSeq(X, Y, X.length(), Y.length()));
}
}
|
Python3
def superSeq(X, Y, m, n):
dp = [[ 0 ] * (n + 2 ) for i in range (m + 2 )]
for i in range (m + 1 ):
for j in range (n + 1 ):
if ( not i):
dp[i][j] = j
elif ( not j):
dp[i][j] = i
elif (X[i - 1 ] = = Y[j - 1 ]):
dp[i][j] = 1 + dp[i - 1 ][j - 1 ]
else :
dp[i][j] = 1 + min (dp[i - 1 ][j],
dp[i][j - 1 ])
return dp[m][n]
X = "AGGTAB"
Y = "GXTXAYB"
print ( "Length of the shortest supersequence is %d"
% superSeq(X, Y, len (X), len (Y)))
|
C#
using System;
class GFG {
static int superSeq(String X, String Y, int m, int n)
{
int [, ] dp = new int [m + 1, n + 1];
for ( int i = 0; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
if (i == 0)
dp[i, j] = j;
else if (j == 0)
dp[i, j] = i;
else if (X[i - 1] == Y[j - 1])
dp[i, j] = 1 + dp[i - 1, j - 1];
else
dp[i, j] = 1
+ Math.Min(dp[i - 1, j],
dp[i, j - 1]);
}
}
return dp[m, n];
}
public static void Main()
{
String X = "AGGTAB" ;
String Y = "GXTXAYB" ;
Console.WriteLine(
"Length of the shortest supersequence is "
+ superSeq(X, Y, X.Length, Y.Length));
}
}
|
PHP
<?php
function superSeq( $X , $Y , $m , $n )
{
$dp = array_fill (0, $m + 1,
array_fill (0, $n + 1, 0));
for ( $i = 0; $i <= $m ; $i ++)
{
for ( $j = 0; $j <= $n ; $j ++)
{
if (! $i )
$dp [ $i ][ $j ] = $j ;
else if (! $j )
$dp [ $i ][ $j ] = $i ;
else if ( $X [ $i - 1] == $Y [ $j - 1])
$dp [ $i ][ $j ] = 1 + $dp [ $i - 1][ $j - 1];
else
$dp [ $i ][ $j ] = 1 + min( $dp [ $i - 1][ $j ],
$dp [ $i ][ $j - 1]);
}
}
return $dp [ $m ][ $n ];
}
$X = "AGGTAB" ;
$Y = "GXTXAYB" ;
echo "Length of the shortest supersequence is " .
superSeq( $X , $Y , strlen ( $X ), strlen ( $Y ));
?>
|
Javascript
<script>
function superSeq(X, Y, m, n)
{
var dp = Array(m+1).fill(0).map(x => Array(n+1).fill(0));
for ( var i = 0; i <= m; i++)
{
for ( var j = 0; j <= n; j++)
{
if (i == 0)
dp[i][j] = j;
else if (j == 0)
dp[i][j] = i;
else if (X.charAt(i - 1) == Y.charAt(j - 1))
dp[i][j] = 1 + dp[i - 1][j - 1];
else
dp[i][j] = 1
+ Math.min(dp[i - 1][j],
dp[i][j - 1]);
}
}
return dp[m][n];
}
var X = "AGGTAB" ;
var Y = "GXTXAYB" ;
document.write(
"Length of the shortest supersequence is "
+ superSeq(X, Y, X.length, Y.length));
</script>
|
Output
Length of the shortest supersequence is 9
Time Complexity: O(m*n).
Auxiliary Space: O(m*n)
Thanks to Gaurav Ahirwar for suggesting this solution.
Method 4 (Top Down Memoization Approach):
The idea is to follow the simple recursive solution, and use a lookup table to avoid re-computations. Before computing the result for input, we check if the result is already computed or not. If already computed, we return that result.
C++
#include <bits/stdc++.h>
using namespace std;
int superSeq(string X, string Y, int n, int m,
vector<vector< int > > lookup)
{
if (m == 0 || n == 0) {
lookup[n][m] = n + m;
}
if (lookup[n][m] == 0)
if (X[n - 1] == Y[m - 1]) {
lookup[n][m]
= superSeq(X, Y, n - 1, m - 1, lookup) + 1;
}
else {
lookup[n][m]
= min(superSeq(X, Y, n - 1, m, lookup) + 1,
superSeq(X, Y, n, m - 1, lookup) + 1);
}
return lookup[n][m];
}
int main()
{
string X = "AGGTB" ;
string Y = "GXTXAYB" ;
vector<vector< int > > lookup(
X.size() + 1, vector< int >(Y.size() + 1, 0));
cout << "Length of the shortest supersequence is "
<< superSeq(X, Y, X.size(), Y.size(), lookup)
<< endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
static int superSeq(String X, String Y, int n, int m,
int [][] lookup)
{
if (m == 0 || n == 0 ) {
lookup[n][m] = n + m;
}
if (lookup[n][m] == 0 )
if (X.charAt(n - 1 ) == Y.charAt(m - 1 )) {
lookup[n][m]
= superSeq(X, Y, n - 1 , m - 1 , lookup)
+ 1 ;
}
else {
lookup[n][m] = Math.min(
superSeq(X, Y, n - 1 , m, lookup) + 1 ,
superSeq(X, Y, n, m - 1 , lookup) + 1 );
}
return lookup[n][m];
}
public static void main(String[] args)
{
String X = "AGGTB" ;
String Y = "GXTXAYB" ;
int [][] lookup
= new int [X.length() + 1 ][Y.length() + 1 ];
System.out.print(
"Length of the shortest supersequence is "
+ superSeq(X, Y, X.length(), Y.length(), lookup)
+ "\n" );
}
}
|
Python3
def superSeq(X,Y,n,m,lookup):
if m = = 0 or n = = 0 :
lookup[n][m] = n + m
if (lookup[n][m] = = 0 ):
if X[n - 1 ] = = Y[m - 1 ]:
lookup[n][m] = superSeq(X,Y,n - 1 ,m - 1 ,lookup) + 1
else :
lookup[n][m] = min (superSeq(X,Y,n - 1 ,m,lookup) + 1 ,
superSeq(X,Y,n,m - 1 ,lookup) + 1 )
return lookup[n][m]
X = "AGGTAB"
Y = "GXTXAYB"
lookup = [[ 0 for j in range ( len (Y) + 1 )] for i in range ( len (X) + 1 )]
print ( "Length of the shortest supersequence is {}"
. format (superSeq(X,Y, len (X), len (Y),lookup)))
|
C#
using System;
public class GFG {
static int superSeq(String X, String Y, int n,
int m, int [,] lookup)
{
if (m == 0 || n == 0) {
lookup[n, m] = n + m;
}
if (lookup[n, m] == 0)
if (X[n - 1] == Y[m - 1]) {
lookup[n, m] = superSeq(X, Y, n - 1,
m - 1, lookup) + 1;
}
else {
lookup[n, m] = Math.Min(superSeq(X, Y, n - 1, m, lookup) +
1, superSeq(X, Y, n, m - 1, lookup) +
1);
}
return lookup[n, m];
}
public static void Main(String[] args) {
String X = "AGGTB" ;
String Y = "GXTXAYB" ;
int [,] lookup = new int [X.Length + 1,Y.Length + 1];
Console.Write(
"Length of the shortest supersequence is " +
superSeq(X, Y, X.Length, Y.Length, lookup) + "\n" );
}
}
|
Javascript
<script>
function superSeq( X, Y , n , m, lookup) {
if (m == 0 || n == 0) {
lookup[n][m] = n + m;
}
if (lookup[n][m] == 0)
if (X.charAt(n - 1) == Y.charAt(m - 1)) {
lookup[n][m] = superSeq(X, Y, n - 1, m - 1, lookup) + 1;
}
else {
lookup[n][m] = Math.min(superSeq(X, Y, n - 1, m, lookup) + 1, superSeq(X, Y, n, m - 1, lookup) + 1);
}
return lookup[n][m];
}
var X = "AGGTB" ;
var Y = "GXTXAYB" ;
var lookup = Array(X.length + 1).fill().map(()=>Array(Y.length + 1).fill(0));
document.write(
"Length of the shortest supersequence is "
+ superSeq(X, Y, X.length, Y.length, lookup) + "\n" );
</script>
|
Output
Length of the shortest supersequence is 9
Time Complexity: O(n*m)
Auxiliary Space: O(n*m)
Exercise:
Extend the above program to print shortest super sequence also using function to print LCS.
Please refer Printing Shortest Common Supersequence for solution
References:
https://en.wikipedia.org/wiki/Shortest_common_supersequence
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!