Shortest possible combination of two strings
Compute the shortest string for a combination of two given strings such that the new string consist of both the strings as its subsequences.
Examples :
Input : a = "pear" b = "peach" Output : pearch pearch is the shorted string such that both pear and peach are its subsequences. Input : a = "geek" b = "code" Output : gecodek
We have discussed a solution to find length of the shortest supersequence in below post.
Shortest Common Supersequence
In this post, printing of supersequence is discussed. The solution is based on below recursive approach discussed in above post as an alternate method.
Let a[0..m-1] and b[0..n-1] be two strings and m and 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 a[] if (a[m-1] == b[n-1]) return 1 + SCS(a, b, 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(a, b, m-1, n), SCS(a, b, m, n-1) );
We build a DP array to store lengths. After building the DP array, we traverse from bottom right most position. The approach of printing is similar to printing LCS.
C++
/* C++ program to print supersequence of two strings */ #include<bits/stdc++.h> using namespace std; /* Prints super sequence of a[0..m-1] and b[0..n-1] */ void printSuperSeq(string &a, string &b) { int m = a.length(), n = b.length(); int dp[m+1][n+1]; // Fill table in bottom up manner for ( int i = 0; i <= m; i++) { for ( int j = 0; j <= n; j++) { // Below steps follow above recurrence if (!i) dp[i][j] = j; else if (!j) dp[i][j] = i; else if (a[i-1] == b[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]); } } // Following code is used to print supersequence int index = dp[m][n]; // Create a string of size index+1 to store the result string res(index+1, '\0' ); // Start from the right-most-bottom-most corner and // one by one store characters in res[] int i = m, j = n; while (i > 0 && j > 0) { // If current character in a[] and b are same, // then current character is part of LCS if (a[i-1] == b[j-1]) { // Put current character in result res[index-1] = a[i-1]; // reduce values of i, j and indexs i--; j--; index--; } // If not same, then find the larger of two and // go in the direction of larger value else if (dp[i-1][j] < dp[i][j-1]) { res[index-1] = a[i-1]; i--; index--; } else { res[index-1] = b[j-1]; j--; index--; } } // Copy remaining characters of string 'a' while (i > 0) { res[index-1] = a[i-1]; i--; index--; } // Copy remaining characters of string 'b' while (j > 0) { res[index-1] = b[j-1]; j--; index--; } // Print the result cout << res; } /* Driver program to test above function */ int main() { string a = "algorithm" , b = "rhythm" ; printSuperSeq(a, b); return 0; } |
Java
// Java program to print supersequence of two // strings public class GFG_1 { String a , b; // Prints super sequence of a[0..m-1] and b[0..n-1] static void printSuperSeq(String a, String b) { int m = a.length(), n = b.length(); int [][] dp = new int [m+ 1 ][n+ 1 ]; // Fill table in bottom up manner for ( int i = 0 ; i <= m; i++) { for ( int j = 0 ; j <= n; j++) { // Below steps follow above recurrence if (i == 0 ) dp[i][j] = j; else if (j == 0 ) dp[i][j] = i; else if (a.charAt(i- 1 ) == b.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 ]); } } // Create a string of size index+1 to store the result String res = "" ; // Start from the right-most-bottom-most corner and // one by one store characters in res[] int i = m, j = n; while (i > 0 && j > 0 ) { // If current character in a[] and b are same, // then current character is part of LCS if (a.charAt(i- 1 ) == b.charAt(j- 1 )) { // Put current character in result res = a.charAt(i- 1 ) + res; // reduce values of i, j and indexs i--; j--; } // If not same, then find the larger of two and // go in the direction of larger value else if (dp[i- 1 ][j] < dp[i][j- 1 ]) { res = a.charAt(i- 1 ) + res; i--; } else { res = b.charAt(j- 1 ) + res; j--; } } // Copy remaining characters of string 'a' while (i > 0 ) { res = a.charAt(i- 1 ) + res; i--; } // Copy remaining characters of string 'b' while (j > 0 ) { res = b.charAt(j- 1 ) + res; j--; } // Print the result System.out.println(res); } /* Driver program to test above function */ public static void main(String args[]) { String a = "algorithm" ; String b = "rhythm" ; printSuperSeq(a, b); } } // This article is contributed by Sumit Ghosh |
C#
// C# program to print supersequence of two // strings using System; public class GFG_1 { // Prints super sequence of a[0..m-1] and b[0..n-1] static void printSuperSeq( string a, string b) { int m = a.Length, n = b.Length; int [,] dp = new int [m+1,n+1]; // Fill table in bottom up manner for ( int i = 0; i <= m; i++) { for ( int j = 0; j <= n; j++) { // Below steps follow above recurrence if (i == 0) dp[i,j] = j; else if (j == 0 ) dp[i,j] = i; else if (a[i-1] == b[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]); } } // Create a string of size index+1 to store the result string res = "" ; // Start from the right-most-bottom-most corner and // one by one store characters in res[] int k = m, l = n; while (k > 0 && l > 0) { // If current character in a[] and b are same, // then current character is part of LCS if (a[k-1] == b[l-1]) { // Put current character in result res = a[k-1] + res; // reduce values of i, j and indexs k--; l--; } // If not same, then find the larger of two and // go in the direction of larger value else if (dp[k-1,l] < dp[k,l-1]) { res = a[k-1] + res; k--; } else { res = b[l-1] + res; l--; } } // Copy remaining characters of string 'a' while (k > 0) { res = a[k-1] + res; k--; } // Copy remaining characters of string 'b' while (l > 0) { res = b[l-1] + res; l--; } // Print the result Console.WriteLine(res); } /* Driver program to test above function */ public static void Main() { string a = "algorithm" ; string b = "rhythm" ; printSuperSeq(a, b); } } // This article is contributed by Ita_c. |
Output:
algorihythm
Solution based on LCS:
We build the 2D array using LCS solution. If the character at the two pointer positions is equal, we increment the length by 1, else we store the minimum of the adjacent positions. Finally, we backtrack the matrix to find the index vector traversing which would yield the shortest possible combination.
C++
// C++ implementation to find shortest string for // a combination of two strings #include <bits/stdc++.h> using namespace std; // Vector that store the index of string a and b vector< int > index_a; vector< int > index_b; // Subroutine to Backtrack the dp matrix to // find the index vector traversing which would // yield the shortest possible combination void index( int dp[][100], string a, string b, int size_a, int size_b) { // Clear the index vectors index_a.clear(); index_b.clear(); // Return if either of a or b is reduced // to 0 if (size_a == 0 || size_b == 0) return ; // Push both to index_a and index_b with // the respective a and b index if (a[size_a - 1] == b[size_b - 1]) { index(dp, a, b, size_a - 1, size_b - 1); index_a.push_back(size_a - 1); index_b.push_back(size_b - 1); } else { if (dp[size_a - 1][size_b] > dp[size_a] [size_b - 1]) { index(dp, a, b, size_a - 1, size_b); } else { index(dp, a, b, size_a, size_b - 1); } } } // function to combine the strings to form // the shortest string void combine(string a, string b, int size_a, int size_b) { int dp[100][100]; string ans = "" ; int k = 0; // Initialize the matrix to 0 memset (dp, 0, sizeof (dp)); // Store the increment of diagonally // previous value if a[i-1] and b[j-1] are // equal, else store the max of dp[i][j-1] // and dp[i-1][j] for ( int i = 1; i <= size_a; i++) { for ( int j = 1; j <= size_b; j++) { if (a[i - 1] == b[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); } } } // Get the Lowest Common Subsequence int lcs = dp[size_a][size_b]; // Backtrack the dp array to get the index // vectors of two strings, used to find // the shortest possible combination. index(dp, a, b, size_a, size_b); int i, j = i = k; // Build the string combination using the // index found by backtracking while (k < lcs) { while (i < size_a && i < index_a[k]) { ans += a[i++]; } while (j < size_b && j < index_b[k]) { ans += b[j++]; } ans = ans + a[index_a[k]]; k++; i++; j++; } // Append the remaining characters in a // to answer while (i < size_a) { ans += a[i++]; } // Append the remaining characters in b // to answer while (j < size_b) { ans += b[j++]; } cout << ans; } // Driver code int main() { string a = "algorithm" ; string b = "rhythm" ; // Store the length of string int size_a = a.size(); int size_b = b.size(); combine(a, b, size_a, size_b); return 0; } |
Java
// Java implementation to find shortest string for // a combination of two strings import java.util.ArrayList; public class GFG_2 { // Vector that store the index of string a and b static ArrayList<Integer> index_a = new ArrayList<>(); static ArrayList<Integer> index_b = new ArrayList<>(); // Subroutine to Backtrack the dp matrix to // find the index vector traversing which would // yield the shortest possible combination static void index( int dp[][], String a, String b, int size_a, int size_b) { // Clear the index vectors index_a.clear(); index_b.clear(); // Return if either of a or b is reduced // to 0 if (size_a == 0 || size_b == 0 ) return ; // Push both to index_a and index_b with // the respective a and b index if (a.charAt(size_a - 1 ) == b.charAt(size_b - 1 )) { index(dp, a, b, size_a - 1 , size_b - 1 ); index_a.add(size_a - 1 ); index_b.add(size_b - 1 ); } else { if (dp[size_a - 1 ][size_b] > dp[size_a] [size_b - 1 ]) { index(dp, a, b, size_a - 1 , size_b); } else { index(dp, a, b, size_a, size_b - 1 ); } } } // function to combine the strings to form // the shortest string static void combine(String a, String b, int size_a, int size_b) { int [][] dp = new int [ 100 ][ 100 ]; String ans = "" ; int k = 0 ; // Store the increment of diagonally // previous value if a[i-1] and b[j-1] are // equal, else store the max of dp[i][j-1] // and dp[i-1][j] for ( int i = 1 ; i <= size_a; i++) { for ( int j = 1 ; j <= size_b; j++) { if (a.charAt(i - 1 ) == b.charAt(j - 1 )) { dp[i][j] = dp[i - 1 ][j - 1 ] + 1 ; } else { dp[i][j] = Math.max(dp[i][j - 1 ], dp[i - 1 ][j]); } } } // Get the Lowest Common Subsequence int lcs = dp[size_a][size_b]; // Backtrack the dp array to get the index // vectors of two strings, used to find // the shortest possible combination. index(dp, a, b, size_a, size_b); int i, j = i = k; // Build the string combination using the // index found by backtracking while (k < lcs) { while (i < size_a && i < index_a.get(k)) { ans += a.charAt(i++); } while (j < size_b && j < index_b.get(k)) { ans += b.charAt(j++); } ans = ans + a.charAt(index_a.get(k)); k++; i++; j++; } // Append the remaining characters in a // to answer while (i < size_a) { ans += a.charAt(i++); } // Append the remaining characters in b // to answer while (j < size_b) { ans += b.charAt(j++); } System.out.println(ans); } /* Driver program to test above function */ public static void main(String args[]) { String a = "algorithm" ; String b = "rhythm" ; combine(a, b, a.length(),b.length()); } } // This article is contributed by Sumit Ghosh |
Output:
algorihythm
This article is contributed by Raghav Jajodia. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Recommended Posts:
- Count number of strings (made of R, G and B) using given combination
- Sum of products of all combination taken (1 to n) at a time
- Find the resulting Colour Combination
- Python | Print all string combination from given numbers
- Search in an array of strings where non-empty strings are sorted
- Meta Strings (Check if two strings can become same after a swap in one string)
- Number of common base strings for two strings
- Count of strings that become equal to one of the two strings after one removal
- Pairs of complete strings in two sets of strings
- Shortest Uncommon Subsequence
- Shortest Common Supersequence
- Shortest Superstring Problem
- Multistage Graph (Shortest Path)
- Printing Shortest Common Supersequence
- Shortest substring of a string containing all given words
Improved By : Ita_c