Print all interleavings of given two strings
Last Updated :
19 Sep, 2023
Given two strings str1 and str2, write a function that prints all interleavings of the given two strings. You may assume that all characters in both strings are different
Example:
Input: str1 = "AB", str2 = "CD"
Output:
ABCD
ACBD
ACDB
CABD
CADB
CDAB
Input: str1 = "AB", str2 = "C"
Output:
ABC
ACB
CAB
An interleaved string of given two strings preserves the order of characters in individual strings. For example, in all the interleavings of above first example, ‘A’ comes before ‘B’ and ‘C’ comes before ‘D’.
Let the length of str1 be m and the length of str2 be n. Let us assume that all characters in str1 and str2 are different. Let count(m, n) be the count of all interleaved strings in such strings. The value of count(m, n) can be written as following.
count(m, n) = count(m-1, n) + count(m, n-1)
count(1, 0) = 1 and count(0, 1) = 1
To print all interleavings, we can first fix the first character of str1[0..m-1] in output string, and recursively call for str1[1..m-1] and str2[0..n-1]. And then we can fix the first character of str2[0..n-1] and recursively call for str1[0..m-1] and str2[1..n-1]. Thanks to akash01 for providing following C implementation.
C++
#include <bits/stdc++.h>
using namespace std;
void printIlsRecur ( char *str1, char *str2, char *iStr, int m,
int n, int i)
{
if (m == 0 && n == 0)
cout << iStr << endl ;
if (m != 0)
{
iStr[i] = str1[0];
printIlsRecur (str1 + 1, str2, iStr, m - 1, n, i + 1);
}
if (n != 0)
{
iStr[i] = str2[0];
printIlsRecur(str1, str2 + 1, iStr, m, n - 1, i + 1);
}
}
void printIls ( char *str1, char *str2, int m, int n)
{
char *iStr= new char [((m + n + 1)* sizeof ( char ))];
iStr[m + n] = '\0' ;
printIlsRecur (str1, str2, iStr, m, n, 0);
free (iStr);
}
int main()
{
char str1[] = "AB" ;
char str2[] = "CD" ;
printIls (str1, str2, strlen (str1), strlen (str2));
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printIlsRecur ( char *str1, char *str2, char *iStr, int m,
int n, int i)
{
if (m==0 && n==0)
printf ( "%s\n" , iStr) ;
if (m != 0)
{
iStr[i] = str1[0];
printIlsRecur (str1 + 1, str2, iStr, m-1, n, i+1);
}
if (n != 0)
{
iStr[i] = str2[0];
printIlsRecur(str1, str2+1, iStr, m, n-1, i+1);
}
}
void printIls ( char *str1, char *str2, int m, int n)
{
char *iStr= ( char *) malloc ((m+n+1)* sizeof ( char ));
iStr[m+n] = '\0' ;
printIlsRecur (str1, str2, iStr, m, n, 0);
free (iStr);
}
int main()
{
char str1[] = "AB" ;
char str2[] = "CD" ;
printIls (str1, str2, strlen (str1), strlen (str2));
return 0;
}
|
Java
import java.io.*;
class GFG {
static void printInterLeaving(String s1, int i,
String s2, int j,
String asf)
{
if (i == s1.length() && j == s2.length()) {
System.out.println(asf);
}
if (i < s1.length())
printInterLeaving(s1, i + 1 , s2, j,
asf + s1.charAt(i));
if (j < s2.length())
printInterLeaving(s1, i, s2, j + 1 ,
asf + s2.charAt(j));
}
public static void main(String[] args)
{
String s1 = "AB" ;
String s2 = "CD" ;
printInterLeaving(s1, 0 , s2, 0 , "" );
}
}
|
Python3
def toString( List ):
return "".join( List )
def printIlsRecur(str1, str2, iStr, m, n, i):
if m = = 0 and n = = 0 :
print (toString(iStr))
if m ! = 0 :
iStr[i] = str1[ 0 ]
printIlsRecur(str1[ 1 :], str2, iStr, m - 1 , n, i + 1 )
if n ! = 0 :
iStr[i] = str2[ 0 ]
printIlsRecur(str1, str2[ 1 :], iStr, m, n - 1 , i + 1 )
def printIls(str1, str2, m, n):
iStr = [''] * (m + n)
printIlsRecur(str1, str2, iStr, m, n, 0 )
str1 = "AB"
str2 = "CD"
printIls(str1, str2, len (str1), len (str2))
|
C#
using System;
public class GFG
{
public static void printInterLeaving(String s1, int i, String s2, int j, String asf)
{
if (i == s1.Length && j == s2.Length)
{
Console.WriteLine(asf);
}
if (i < s1.Length)
{
GFG.printInterLeaving(s1, i + 1, s2, j, asf + s1[i].ToString());
}
if (j < s2.Length)
{
GFG.printInterLeaving(s1, i, s2, j + 1, asf + s2[j].ToString());
}
}
public static void Main(String[] args)
{
var s1 = "AB" ;
var s2 = "CD" ;
GFG.printInterLeaving(s1, 0, s2, 0, "" );
}
}
|
Javascript
function printIlsRecur(str1, str2, iStr, m, n, i)
{
if (m === 0 && n === 0) {
console.log(iStr.join( "" ));
}
if (m !== 0) {
iStr[i] = str1[0];
printIlsRecur(str1.slice(1), str2, iStr, m - 1, n, i + 1);
}
if (n !== 0) {
iStr[i] = str2[0];
printIlsRecur(str1, str2.slice(1), iStr, m, n - 1, i + 1);
}
}
function printIls(str1, str2, m, n) {
let iStr = new Array(m + n);
printIlsRecur(str1, str2, iStr, m, n, 0);
}
let str1 = "AB" ;
let str2 = "CD" ;
printIls(str1, str2, str1.length, str2.length);
|
Output
ABCD
ACBD
ACDB
CABD
CADB
CDAB
Time Complexity: O(2 ^ (m+n))
Auxiliary Space: O(1)
Approach 2: Using Buttom-Up Approach /Tabulation Method of Dynamic Programming
C++
#include <bits/stdc++.h>
using namespace std;
void printInterleavings(string str1, string str2)
{
int m = str1.length();
int n = str2.length();
vector<vector<vector<string> > > dp(
m + 1, vector<vector<string> >(n + 1));
for ( int i = 0; i <= m; i++) {
dp[i][0] = { str1.substr(0, i) };
}
for ( int j = 0; j <= n; j++) {
dp[0][j] = { str2.substr(0, j) };
}
for ( int i = 1; i <= m; i++) {
for ( int j = 1; j <= n; j++) {
dp[i][j] = dp[i - 1][j];
for (string& s : dp[i][j]) {
s += str1[i - 1];
}
for (string& s : dp[i][j - 1]) {
dp[i][j].push_back(s + str2[j - 1]);
}
}
}
for ( const string& interleaved : dp[m][n]) {
cout << interleaved << endl;
}
}
int main()
{
string str1 = "AB" ;
string str2 = "CD" ;
printInterleavings(str1, str2);
return 0;
}
|
Java
import java.util.ArrayList;
public class GFG {
static void printInterleavings(String str1, String str2) {
int m = str1.length();
int n = str2.length();
ArrayList<ArrayList<ArrayList<String>>> dp = new ArrayList<>();
for ( int i = 0 ; i <= m; i++) {
ArrayList<ArrayList<String>> row = new ArrayList<>();
dp.add(row);
for ( int j = 0 ; j <= n; j++) {
row.add( new ArrayList<>());
}
}
for ( int i = 0 ; i <= m; i++) {
dp.get(i).get( 0 ).add(str1.substring( 0 , i));
}
for ( int j = 0 ; j <= n; j++) {
dp.get( 0 ).get(j).add(str2.substring( 0 , j));
}
for ( int i = 1 ; i <= m; i++) {
for ( int j = 1 ; j <= n; j++) {
for (String s : dp.get(i - 1 ).get(j)) {
dp.get(i).get(j).add(s + str1.charAt(i - 1 ));
}
for (String s : dp.get(i).get(j - 1 )) {
dp.get(i).get(j).add(s + str2.charAt(j - 1 ));
}
}
}
for (String interleaved : dp.get(m).get(n)) {
System.out.println(interleaved);
}
}
public static void main(String[] args) {
String str1 = "AB" ;
String str2 = "CD" ;
printInterleavings(str1, str2);
}
}
|
Python
def printInterleavings(str1, str2):
m, n = len (str1), len (str2)
dp = [[[] for _ in range (n + 1 )] for _ in range (m + 1 )]
for i in range (m + 1 ):
dp[i][ 0 ] = [str1[:i]]
for j in range (n + 1 ):
dp[ 0 ][j] = [str2[:j]]
for i in range ( 1 , m + 1 ):
for j in range ( 1 , n + 1 ):
dp[i][j] + = [s + str1[i - 1 ] for s in dp[i - 1 ][j]]
dp[i][j] + = [s + str2[j - 1 ] for s in dp[i][j - 1 ]]
for interleaved in dp[m][n]:
print (interleaved)
str1 = "AB"
str2 = "CD"
printInterleavings(str1, str2)
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static void PrintInterleavings( string str1, string str2)
{
int m = str1.Length;
int n = str2.Length;
List<List<List< string >>> dp = new List<List<List< string >>>();
for ( int i = 0; i <= m; i++)
{
List<List< string >> row = new List<List< string >>();
dp.Add(row);
for ( int j = 0; j <= n; j++)
{
row.Add( new List< string >());
}
}
for ( int i = 0; i <= m; i++)
{
dp[i][0].Add(str1.Substring(0, i));
}
for ( int j = 0; j <= n; j++)
{
dp[0][j].Add(str2.Substring(0, j));
}
for ( int i = 1; i <= m; i++)
{
for ( int j = 1; j <= n; j++)
{
foreach ( string s in dp[i - 1][j])
{
dp[i][j].Add(s + str1[i - 1]);
}
foreach ( string s in dp[i][j - 1])
{
dp[i][j].Add(s + str2[j - 1]);
}
}
}
foreach ( string interleaved in dp[m][n])
{
Console.WriteLine(interleaved);
}
}
public static void Main( string [] args)
{
string str1 = "AB" ;
string str2 = "CD" ;
PrintInterleavings(str1, str2);
}
}
|
Javascript
function printInterleavings(str1, str2) {
const m = str1.length;
const n = str2.length;
const dp = new Array(m + 1).fill( null ).map(() =>
new Array(n + 1));
for (let i = 0; i <= m; i++) {
dp[i][0] = [str1.slice(0, i)];
}
for (let j = 0; j <= n; j++) {
dp[0][j] = [str2.slice(0, j)];
}
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
dp[i][j] = dp[i - 1][j].map(s => s + str1[i - 1]);
dp[i][j] = dp[i][j] || [];
dp[i][j].push(...dp[i][j - 1].map(s => s + str2[j - 1]));
}
}
for (const interleaved of dp[m][n]) {
console.log(interleaved);
}
}
const str1 = "AB" ;
const str2 = "CD" ;
printInterleavings(str1, str2);
|
Output
CDAB
CADB
ACDB
CABD
ACBD
ABCD
Time complexity: O(m * n * L), where m and n are the lengths of str1 and str2 respectively, and L is the average length of the interleaved strings.
Auxiliary Space: O(m * n * L), where m and n are the lengths of str1 and str2 respectively, and L is the average length of the interleaved strings.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...