Printing Shortest Common Supersequence
Given two strings s1 and s2, find the shortest string which has both s1 and s2 as its sub-sequences. If multiple shortest super-sequence exists, print any one of them.
Examples:
Input: s1 = "geek", s2 = "eke"
Output: geeke
Explanation: String "geeke" has both string "geek" and "eke" as subsequences.
Input: s1 = "AGGTAB", s2 = "GXTXAYB"
Output: AGXGTXAYB
Explanation: String "AGXGTXAYB" has both string "AGGTAB" and "GXTXAYB" as subsequences.
Approach:
The idea is to find the shortest common supersequence (SCS) of two strings by using a dynamic programming (DP) table to calculate the minimum length of the merged string while preserving character order. It builds the SCS by backtracking from the DP table, adding common characters when they match and choosing the smaller cost path when they don’t. Finally, the result is reversed as it’s constructed backward.
To solve the problem, we use a DP table where dp[i][j]
represents the length of the shortest common supersequence (SCS) for the first i
characters of s1
and the first j
characters of s2
.
Base Cases:
- dp[0][j]: If s1 is empty, SCS is all characters of s2, so dp[0][j] = j.
- dp[i][0]: If s2 is empty, SCS is all characters of s1, so dp[i][0] = i.
Filling the Table:
Case 1: If s1[i-1] == s2[j-1]:
- When the current characters of s1 and s2 are the same, they must appear only once in the SCS. So, we add 1 to the result of the SCS for the previous characters (dp[i-1][j-1]).
Case 2: If s1[i-1] != s2[j-1]:
- When the current characters differ, we have two choices:
- Include the character from s1 (add 1 to dp[i-1][j]), which means the SCS considers this character of s1.
- Include the character from s2 (add 1 to dp[i][j-1]), which means the SCS considers this character of s2. We take the minimum of these two, as we want the shortest sequence.
The following table shows steps followed by the above algorithm if we solve it in bottom-up manner using Dynamic Programming for strings X = “AGGTAB” and Y = “GXTXAYB”,

Construct the SCS
The DP table is filled row by row, starting from dp[0][0]
up to dp[m][n]
, where m
and n
are the lengths of s1
and s2
. After filling the table, dp[m][n]
contains the length of the shortest common supersequence.
- Begin at the bottom-right cell (
dp[m][n]
), representing the SCS for the full stringss1
ands2
. - Case 1 (Characters Match):
- If
s1[i-1] == s2[j-1]
, the current character is part of the SCS. - Add it to the result and move diagonally (
i--, j--
).
- If
- Case 2 (Characters Differ):
- Compare
dp[i-1][j]
anddp[i][j-1]
to find the smaller value. - If
dp[i-1][j] < dp[i][j-1]
, includes1[i-1]
in the result and move up (i--
). - Otherwise, include
s2[j-1]
and move left (j--
).
- Compare
- Handling Remaining Characters:
- If
i == 0
, append the remaining characters ofs2
to the result. - If
j == 0
, append the remaining characters ofs1
to the result.
- If
- Reverse the Result:
- Since the result is built backward, reverse it at the end to obtain the final SCS.
#include <bits/stdc++.h>
using namespace std;
// Function to find and print the shortest common
// supersequence of two strings.
string shortestCommonSupersequence(string& s1, string& s2) {
int m = s1.size(), n = s2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
// Filling the dp table
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 (s1[i - 1] == s2[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]);
}
}
}
// Constructing the shortest supersequence from dp table
int i = m, j = n;
string result = "";
while (i > 0 && j > 0) {
if (s1[i - 1] == s2[j - 1]) {
result += s1[i - 1];
i--, j--;
} else if (dp[i - 1][j] < dp[i][j - 1]) {
result += s1[i - 1];
i--;
} else {
result += s2[j - 1];
j--;
}
}
// Adding remaining characters
while (i > 0) {
result += s1[i - 1];
i--;
}
while (j > 0) {
result += s2[j - 1];
j--;
}
// Reverse the result since we built it backwards
reverse(result.begin(), result.end());
return result;
}
int main() {
string s1 = "AGGTAB";
string s2 = "GXTXAYB";
cout << shortestCommonSupersequence(s1, s2);
return 0;
}
import java.util.*;
class GfG {
// Function to find and return the shortest common supersequence
static String shortestCommonSupersequence(String s1, String s2) {
int m = s1.length(), n = s2.length();
int[][] dp = new int[m + 1][n + 1];
// Filling the dp table
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 (s1.charAt(i - 1) == s2.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]);
}
}
}
// Constructing the shortest supersequence
int i = m, j = n;
StringBuilder result = new StringBuilder();
while (i > 0 && j > 0) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
result.append(s1.charAt(i - 1));
i--;
j--;
} else if (dp[i - 1][j] < dp[i][j - 1]) {
result.append(s1.charAt(i - 1));
i--;
} else {
result.append(s2.charAt(j - 1));
j--;
}
}
// Adding remaining characters
while (i > 0) {
result.append(s1.charAt(i - 1));
i--;
}
while (j > 0) {
result.append(s2.charAt(j - 1));
j--;
}
return result.reverse().toString();
}
public static void main(String[] args) {
String s1 = "AGGTAB";
String s2 = "GXTXAYB";
System.out.println(shortestCommonSupersequence(s1, s2));
}
}
def shortest_common_supersequence(s1, s2):
m, n = len(s1), len(s2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
# Filling the dp table
for i in range(m + 1):
for j in range(n + 1):
if i == 0:
dp[i][j] = j
elif j == 0:
dp[i][j] = i
elif s1[i - 1] == s2[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])
# Constructing the shortest supersequence
i, j = m, n
result = []
while i > 0 and j > 0:
if s1[i - 1] == s2[j - 1]:
result.append(s1[i - 1])
i -= 1
j -= 1
elif dp[i - 1][j] < dp[i][j - 1]:
result.append(s1[i - 1])
i -= 1
else:
result.append(s2[j - 1])
j -= 1
# Adding remaining characters
while i > 0:
result.append(s1[i - 1])
i -= 1
while j > 0:
result.append(s2[j - 1])
j -= 1
return "".join(result[::-1])
if __name__ == "__main__":
s1 = "AGGTAB"
s2 = "GXTXAYB"
print(shortest_common_supersequence(s1, s2))
using System;
class GfG {
// Function to find and return the shortest common supersequence
public static string ShortestCommonSupersequence(string s1, string s2) {
int m = s1.Length, n = s2.Length;
int[,] dp = new int[m + 1, n + 1];
// Filling the dp table
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 (s1[i - 1] == s2[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]);
}
}
}
// Constructing the shortest supersequence
int x = m, y = n;
string result = "";
while (x > 0 && y > 0) {
if (s1[x - 1] == s2[y - 1]) {
result = s1[x - 1] + result;
x--;
y--;
} else if (dp[x - 1, y] < dp[x, y - 1]) {
result = s1[x - 1] + result;
x--;
} else {
result = s2[y - 1] + result;
y--;
}
}
// Adding remaining characters
while (x > 0) {
result = s1[x - 1] + result;
x--;
}
while (y > 0) {
result = s2[y - 1] + result;
y--;
}
return result;
}
public static void Main() {
string s1 = "AGGTAB";
string s2 = "GXTXAYB";
Console.WriteLine(ShortestCommonSupersequence(s1, s2));
}
}
function shortestCommonSupersequence(s1, s2) {
let m = s1.length, n = s2.length;
let dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
// Filling the dp table
for (let i = 0; i <= m; i++) {
for (let j = 0; j <= n; j++) {
if (i === 0) {
dp[i][j] = j;
} else if (j === 0) {
dp[i][j] = i;
} else if (s1[i - 1] === s2[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]);
}
}
}
// Constructing the shortest supersequence
let i = m, j = n, result = [];
while (i > 0 && j > 0) {
if (s1[i - 1] === s2[j - 1]) {
result.push(s1[i - 1]);
i--;
j--;
} else if (dp[i - 1][j] < dp[i][j - 1]) {
result.push(s1[i - 1]);
i--;
} else {
result.push(s2[j - 1]);
j--;
}
}
// Adding remaining characters
while (i > 0) {
result.push(s1[i - 1]);
i--;
}
while (j > 0) {
result.push(s2[j - 1]);
j--;
}
return result.reverse().join("");
}
// Example usage
let s1 = "AGGTAB";
let s2 = "GXTXAYB";
console.log(shortestCommonSupersequence(s1, s2));
Output
AGGXTXAYB
Time Complexity: O(|str1|*|str2|), as we are running nested loop which is iterating |str1|*|str2| times.
Auxiliary Space: O(|str1|*|str2|), as we are using dp array of size |str1|*|str2|.