Find if a string is interleaved of two other strings | DP-33 - GeeksforGeeks

29 Mar, 2022
Given three strings A, B and C. Write a function that checks whether C is an interleaving of A and B. C is said to be interleaving A and B, if it contains all and only characters of A and B and order of all characters in individual strings is preserved. 
Example: 
Input: strings: "XXXXZY", "XXY", "XXZ"
Output: XXXXZY is interleaved of XXY and XXZ
The string XXXXZY can be made by 
interleaving XXY and XXZ
String:    XXXXZY
String 1:    XX Y
String 2:  XX  Z

Input: strings: "XXY", "YX", "X"
Output: XXY is not interleaved of YX and X
XXY cannot be formed by interleaving YX and X.
The strings that can be formed are YXX and XYX
Simple Solution: Recursion. Approach: A simple solution is discussed here: Check whether a given string is an interleaving of two other given string. The simple solution doesn’t work if the strings A and B have some common characters. For example, let the given string be A and the other strings be B and C. Let A = “XXY”, string B = “XXZ” and string C = “XXZXXXY”. Create a recursive function that takes parameters A, B, and C. To handle all cases, two possibilities need to be considered.
If the first character of C matches the first character of A, we move one character ahead in A and C and recursively check.If the first character of C matches the first character of B, we move one character ahead in B and C and recursively check.
If the first character of C matches the first character of A, we move one character ahead in A and C and recursively check.
If the first character of C matches the first character of B, we move one character ahead in B and C and recursively check.
If any of the above function returns true or A, B and C are empty then return true else return false.Thanks to Frederic for suggesting this approach.
C
// A simple recursive function to check// whether C is an interleaving of A and Bbool isInterleaved(    char* A, char* B, char* C){    // Base Case: If all strings are empty    if (!(*A || *B || *C))        return true;     // If C is empty and any of the    // two strings is not empty    if (*C == '\0')        return false;     // If any of the above mentioned    // two possibilities is true,    // then return true, otherwise false    return ((*C == *A) && isInterleaved(                              A + 1, B, C + 1))           || ((*C == *B) && isInterleaved(                                 A, B + 1, C + 1));}
Complexity Analysis: 
Time Complexity: O(2^n), where n is the length of the given string. We need to iterate the whole string only once hence this is possible in O(n).
Space Complexity: O(1). The space complexity is constant.
Efficient Solution: Dynamic Programming. Approach: The above recursive solution certainly has many overlapping sub-problems. For example, if we consider A = “XXX”, B = “XXX” and C = “XXXXXX” and draw a recursion tree, there will be many overlapping subproblems. Therefore, like any other typical Dynamic Programming problems, we can solve it by creating a table and store results of sub-problems in a bottom-up manner. The top-down approach of the above solution can be modified by adding a Hash Map.
Algorithm: 
Create a DP array (matrix) of size M*N, where m is the size of the first string and n is the size of the second string. Initialize the matrix to false.If the sum of sizes of smaller strings is not equal to the size of the larger string then return false and break the array as they cant be the interleaved to form the larger string.Run a nested loop the outer loop from 0 to m and the inner loop from 0 to n. Loop counters are i and j.If the values of i and j are both zeroes then mark dp[i][j] as true. If the value of i is zero and j is non zero and the j-1 character of B is equal to j-1 character of C the assign dp[i][j] as dp[i][j-1] and similarly if j is 0 then match i-1 th character of C and A and if it matches then assign dp[i][j] as dp[i-1][j].Take three characters x, y, z as (i-1)th character of A and (j-1)th character of B and (i + j – 1)th character of C.if x matches with z and y does not match with z then assign dp[i][j] as dp[i-1][j] similarly if x is not equal to z and y is equal to z then assign dp[i][j] as dp[i][j-1]if x is equal to y and y is equal to z then assign dp[i][j] as bitwise OR of dp[i][j-1] and dp[i-1][j].return value of dp[m][n].
Create a DP array (matrix) of size M*N, where m is the size of the first string and n is the size of the second string. Initialize the matrix to false.
If the sum of sizes of smaller strings is not equal to the size of the larger string then return false and break the array as they cant be the interleaved to form the larger string.
Run a nested loop the outer loop from 0 to m and the inner loop from 0 to n. Loop counters are i and j.
If the values of i and j are both zeroes then mark dp[i][j] as true. If the value of i is zero and j is non zero and the j-1 character of B is equal to j-1 character of C the assign dp[i][j] as dp[i][j-1] and similarly if j is 0 then match i-1 th character of C and A and if it matches then assign dp[i][j] as dp[i-1][j].
Take three characters x, y, z as (i-1)th character of A and (j-1)th character of B and (i + j – 1)th character of C.
if x matches with z and y does not match with z then assign dp[i][j] as dp[i-1][j] similarly if x is not equal to z and y is equal to z then assign dp[i][j] as dp[i][j-1]
if x is equal to y and y is equal to z then assign dp[i][j] as bitwise OR of dp[i][j-1] and dp[i-1][j].
return value of dp[m][n].
Thanks to Abhinav Ramana for suggesting this method of implementation. 
C++
Java
Python3
C#
Javascript
// A Dynamic Programming based program// to check whether a string C is// an interleaving of two other// strings A and B.#include <iostream>#include <string.h>using namespace std; // The main function that// returns true if C is// an interleaving of A// and B, otherwise false.bool isInterleaved(    char* A, char* B, char* C){    // Find lengths of the two strings    int M = strlen(A), N = strlen(B);     // Let us create a 2D table    // to store solutions of    // subproblems.  C[i][j] will    // be true if C[0..i+j-1]    // is an interleaving of    // A[0..i-1] and B[0..j-1].    bool IL[M + 1][N + 1];     // Initialize all values as false.    memset(IL, 0, sizeof(IL));     // C can be an interleaving of    // A and B only of the sum    // of lengths of A & B is equal    // to the length of C.    if ((M + N) != strlen(C))        return false;     // Process all characters of A and B    for (int i = 0; i <= M; ++i) {        for (int j = 0; j <= N; ++j) {            // two empty strings have an            // empty string as interleaving            if (i == 0 && j == 0)                IL[i][j] = true;             // A is empty            else if (i == 0) {                if (B[j - 1] == C[j - 1])                    IL[i][j] = IL[i][j - 1];            }             // B is empty            else if (j == 0) {                if (A[i - 1] == C[i - 1])                    IL[i][j] = IL[i - 1][j];            }             // Current character of C matches            // with current character of A,            // but doesn't match with current            // character of B            else if (                A[i - 1] == C[i + j - 1]                && B[j - 1] != C[i + j - 1])                IL[i][j] = IL[i - 1][j];             // Current character of C matches            // with current character of B,            // but doesn't match with current            // character of A            else if (                A[i - 1] != C[i + j - 1]                && B[j - 1] == C[i + j - 1])                IL[i][j] = IL[i][j - 1];             // Current character of C matches            // with that of both A and B            else if (                A[i - 1] == C[i + j - 1]                && B[j - 1] == C[i + j - 1])                IL[i][j]                    = (IL[i - 1][j]                       || IL[i][j - 1]);        }    }     return IL[M][N];} // A function to run test casesvoid test(char* A, char* B, char* C){    if (isInterleaved(A, B, C))        cout << C << " is interleaved of "             << A << " and " << B << endl;    else        cout << C << " is not interleaved of "             << A << " and " << B << endl;} // Driver program to test above functionsint main(){    test("XXY", "XXZ", "XXZXXXY");    test("XY", "WZ", "WZXY");    test("XY", "X", "XXY");    test("YX", "X", "XXY");    test("XXY", "XXZ", "XXXXZY");    return 0;}
// A Dynamic Programming based program// to check whether a string C is// an interleaving of two other// strings A and B.import java.io.*;import java.util.*;import java.lang.*; class GFG{ // The main function that returns// true if C is an interleaving of A// and B, otherwise false. static boolean isInterleaved(String A, String B,                             String C){         // Find lengths of the two strings    int M = A.length(), N = B.length();     // Let us create a 2D table to store    // solutions of subproblems. C[i][j]    // will be true if C[0..i+j-1] is an    // interleaving of A[0..i-1] and B[0..j-1].    boolean IL[][] = new boolean[M + 1][N + 1];     // IL is default initialised by false     // C can be an interleaving of A and B    // only if the sum of lengths of A and B    // is equal to length of C    if ((M + N) != C.length())        return false;     // Process all characters of A and B     for(int i = 0; i <= M; i++)    {        for(int j = 0; j <= N; j++)        {                         // Two empty strings have an            // empty strings as interleaving            if (i == 0 && j == 0)                IL[i][j] = true;             // A is empty            else if (i == 0)            {                if (B.charAt(j - 1) ==                    C.charAt(j - 1))                    IL[i][j] = IL[i][j - 1];             }             // B is empty            else if (j == 0)            {                if (A.charAt(i - 1) ==                    C.charAt(i - 1))                    IL[i][j] = IL[i - 1][j];            }             // Current character of C matches            // with current character of A,            // but doesn't match with current            // character if B            else if (A.charAt(i - 1) ==                     C.charAt(i + j - 1) &&                     B.charAt(j - 1) !=                     C.charAt(i + j - 1))                IL[i][j] = IL[i - 1][j];             // Current character of C matches            // with current character of B, but            // doesn't match with current            // character if A            else if (A.charAt(i - 1) !=                     C.charAt(i + j - 1) &&                     B.charAt(j - 1) ==                     C.charAt(i + j - 1))                IL[i][j] = IL[i][j - 1];             // Current character of C matches            // with that of both A and B            else if (A.charAt(i - 1) ==                     C.charAt(i + j - 1) &&                     B.charAt(j - 1) ==                     C.charAt(i + j - 1))                IL[i][j] = (IL[i - 1][j] ||                            IL[i][j - 1]);         }    }    return IL[M][N];} // Function to run test casesstatic void test(String A, String B, String C){    if (isInterleaved(A, B, C))        System.out.println(C + " is interleaved of " +                           A + " and " + B);    else        System.out.println(C + " is not interleaved of " +                           A + " and " + B);} // Driver codepublic static void main(String[] args){    test("XXY", "XXZ", "XXZXXXY");    test("XY", "WZ", "WZXY");    test("XY", "X", "XXY");    test("YX", "X", "XXY");    test("XXY", "XXZ", "XXXXZY");}} // This code is contributed by th_aditi
# A Dynamic Programming based python3 program# to check whether a string C is an interleaving# of two other strings A and B. # The main function that returns true if C is# an interleaving of A and B, otherwise false.def isInterleaved(A, B, C):     # Find lengths of the two strings    M = len(A)    N = len(B)     # Let us create a 2D table to store solutions of    # subproblems. C[i][j] will be true if C[0..i + j-1]    # is an interleaving of A[0..i-1] and B[0..j-1].    # Initialize all values as false.    IL = [[False] * (N + 1) for i in range(M + 1)]     # C can be an interleaving of A and B only of sum    # of lengths of A & B is equal to length of C.    if ((M + N) != len(C)):        return False     # Process all characters of A and B    for i in range(0, M + 1):        for j in range(0, N + 1):                         # two empty strings have an empty string            # as interleaving            if (i == 0 and j == 0):                IL[i][j] = True             # A is empty            elif (i == 0):                if (B[j - 1] == C[j - 1]):                    IL[i][j] = IL[i][j - 1]                         # B is empty            elif (j == 0):                if (A[i - 1] == C[i - 1]):                    IL[i][j] = IL[i - 1][j]                         # Current character of C matches with            # current character of A, but doesn't match            # with current character of B            elif (A[i - 1] == C[i + j - 1] and                  B[j - 1] != C[i + j - 1]):                IL[i][j] = IL[i - 1][j]             # Current character of C matches with            # current character of B, but doesn't match            # with current character of A            elif (A[i - 1] != C[i + j - 1] and                  B[j - 1] == C[i + j - 1]):                IL[i][j] = IL[i][j - 1]             # Current character of C matches with            # that of both A and B            elif (A[i - 1] == C[i + j - 1] and                  B[j - 1] == C[i + j - 1]):                IL[i][j] = (IL[i - 1][j] or IL[i][j - 1])             return IL[M][N] # A function to run test casesdef test(A, B, C):     if (isInterleaved(A, B, C)):        print(C, "is interleaved of", A, "and", B)    else:        print(C, "is not interleaved of", A, "and", B) # Driver Codeif __name__ == '__main__':    test("XXY", "XXZ", "XXZXXXY")    test("XY", "WZ", "WZXY")    test("XY", "X", "XXY")    test("YX", "X", "XXY")    test("XXY", "XXZ", "XXXXZY")     # This code is contributed by ashutosh450
// A Dynamic Programming based program // to check whether a string C is // an interleaving of two other // strings A and B.using System;class GFG{         // The main function that returns     // true if C is an interleaving of A     // and B, otherwise false.      static bool isInterleaved(string A, string B,                                  string C)     {                   // Find lengths of the two strings        int M = A.Length, N = B.Length;               // Let us create a 2D table to store        // solutions of subproblems. C[i][j]         // will be true if C[0..i+j-1] is an        // interleaving of A[0..i-1] and B[0..j-1].        bool[ , ] IL = new bool[M + 1, N + 1];               // IL is default initialised by false              // C can be an interleaving of A and B        // only if the sum of lengths of A and B        // is equal to length of C        if ((M + N) != C.Length)            return false;               // Process all characters of A and B         for(int i = 0; i <= M; i++)        {            for(int j = 0; j <= N; j++)            {                                   // Two empty strings have an                // empty strings as interleaving                if (i == 0 && j == 0)                    IL[i, j] = true;                       // A is empty                else if (i == 0)                {                    if (B[j - 1] == C[j - 1])                        IL[i, j] = IL[i, j - 1];                 }                       // B is empty                else if (j == 0)                {                    if (A[i - 1] == C[i - 1])                        IL[i, j] = IL[i - 1, j];                }                       // Current character of C matches                // with current character of A,                 // but doesn't match with current                // character if B                else if (A[i - 1] == C[i + j - 1] &&                          B[j - 1] != C[i + j - 1])                    IL[i, j] = IL[i - 1, j];                       // Current character of C matches                // with current character of B, but                // doesn't match with current                // character if A                else if (A[i - 1] != C[i + j - 1] &&                          B[j - 1] == C[i + j - 1])                        IL[i, j] = IL[i, j - 1];                       // Current character of C matches                // with that of both A and B                else if (A[i - 1] == C[i + j - 1] &&                          B[j - 1] == C[i + j - 1])                       IL[i, j] = (IL[i - 1, j] ||                                 IL[i, j - 1]);             }        }        return IL[M, N];    }           // Function to run test cases    static void test(string A, string B, string C)     {        if (isInterleaved(A, B, C))            Console.WriteLine(C + " is interleaved of " +                               A + " and " + B);        else            Console.WriteLine(C + " is not interleaved of " +                               A + " and " + B);    }       // Driver code  static void Main()  {    test("XXY", "XXZ", "XXZXXXY");    test("XY", "WZ", "WZXY");    test("XY", "X", "XXY");    test("YX", "X", "XXY");    test("XXY", "XXZ", "XXXXZY");  }} // This code is contributed by divyeshrabadiya07
<script> // A Dynamic Programming based program// to check whether a string C is// an interleaving of two other// strings A and B.  // The main function that// returns true if C is// an interleaving of A// and B, otherwise false.function isInterleaved(A, B, C){    // Find lengths of the two strings    let M = A.length, N = B.length;     // Let us create a 2D table    // to store solutions of    // subproblems.  C[i][j] will    // be true if C[0..i+j-1]    // is an interleaving of    // A[0..i-1] and B[0..j-1].    // Initialize all values as false.    let IL = new Array(M + 1);     for(let i=0;i<M+1;i++){        IL[i] = new Array(N + 1).fill(0);    }      // C can be an interleaving of    // A and B only of the sum    // of lengths of A & B is equal    // to the length of C.    if ((M + N) != C.length)        return false;     // Process all characters of A and B    for (let i = 0; i <= M; ++i) {        for (let j = 0; j <= N; ++j) {            // two empty strings have an            // empty string as interleaving            if (i == 0 && j == 0)                IL[i][j] = true;             // A is empty            else if (i == 0) {                if (B[j - 1] == C[j - 1])                    IL[i][j] = IL[i][j - 1];            }             // B is empty            else if (j == 0) {                if (A[i - 1] == C[i - 1])                    IL[i][j] = IL[i - 1][j];            }             // Current character of C matches            // with current character of A,            // but doesn't match with current            // character of B            else if (                A[i - 1] == C[i + j - 1]                && B[j - 1] != C[i + j - 1])                IL[i][j] = IL[i - 1][j];             // Current character of C matches            // with current character of B,            // but doesn't match with current            // character of A            else if (                A[i - 1] != C[i + j - 1]                && B[j - 1] == C[i + j - 1])                IL[i][j] = IL[i][j - 1];             // Current character of C matches            // with that of both A and B            else if (                A[i - 1] == C[i + j - 1]                && B[j - 1] == C[i + j - 1])                IL[i][j]                    = (IL[i - 1][j]                       || IL[i][j - 1]);        }    }     return IL[M][N];} // A function to run test casesfunction test(A, B, C){    if (isInterleaved(A, B, C))        document.write(C + " is interleaved of " + A + " and " + B,"</br>");    else        document.write(C + " is not interleaved of " + A + " and " + B,"</br>");} // Driver program to test above functions test("XXY", "XXZ", "XXZXXXY");test("XY", "WZ", "WZXY");test("XY", "X", "XXY");test("YX", "X", "XXY");test("XXY", "XXZ", "XXXXZY"); // This code is contributed by shinjanpatra</script>
Output: 
XXZXXXY is not interleaved of XXY and XXZ
WZXY is interleaved of XY and WZ
XXY is interleaved of XY and X
XXY is not interleaved of YX and X
XXXXZY is interleaved of XXY and XXZ
See this for more test cases.Complexity Analysis: 
Time Complexity: O(M*N). Since a traversal of DP array is needed, so the time complexity is O(M*N).
Space Complexity: O(M*N). This is the space required to store the DP array.
https://youtu.be/WBXy-sztEwI Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
gp6
ankita91994
ashutosh450
andrew1234
psyduck
divyeshrabadiya07
kashisharora4110
roho
janmanshh
ajaysingh37
prasunroy212
surinderdawra388
shinjanpatra
simmytarika5
prashantchandelme
FactSet
Google
Microsoft
Yahoo
Zillious
Dynamic Programming
Strings
Microsoft
FactSet
Google
Zillious
Yahoo
Strings
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Longest Palindromic Substring | Set 1
Subset Sum Problem | DP-25
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Reverse a string in Java
Write a program to reverse an array or string
C++ Data Types
Write a program to print all permutations of a given string
Check for Balanced Brackets in an expression (well-formedness) using Stack