Open In App

Check if a String is Interleaving of Other Two

Last Updated : 08 Nov, 2025
Comments
Improve
Suggest changes
79 Likes
Like
Report

Give three strings s1, s2 and s3, determine if s3 is formed by interleaving s1 and s2.
A string s3 is an interleaving of s1 and s2 if:

  • It contains all characters of s1 and s2 while preserving their relative order.
  • Characters from s1 and s2 appear in s3 in the same order as in their original strings.
  • The length of s3 equals the combined length of s1 and s2.

Example:

Input: s1 = "AAB", s2 = "AAC", s3 = "AAAABC"
Output: true
Explanation: The string "AAAABC" has all characters of the other two strings and in the same order.

Input: s1 = "YX", s2 = "X", s3 = "XXY"
Output: false
Explanation: "XXY " is not interleaved of "YX" and "X". The strings that can be formed are YXX and XYX.

[Naive Approach] Using Recursion - O(2(m+n)) Time and O(m+n) Auxiliary Space

We want to check if we can form string s3 by using all characters of s1 and s2 in their relative order. This means we can take characters either from s1 or from s2 while forming s3. At every step, we have two choices: Take the character from s1 or take the character from s2, Since we have to try both possibilities, recursion is a perfect fit here.

For doing this we initialise three variable i, j, and k to store the index of string s1, s2, and s3 respectively. For the position in s3, we can easily find the index using k = i + j, because we have already taken i characters from s1 and j characters from s2 to form the prefix of s3. To handle all cases, the following possibilities need to be considered.

  • If the first character of s3 matches the first character of s1, we move one character ahead in s1 and s3 and recursively check.
  • If the first character of s3 matches the first character of s2, we move one character ahead in s2 and s3 and recursively check.
  • If none of the two characters match, return false.
  • If any of the above function returns true or s1, s2 and s3 are empty then return true else return false.
C++
//Driver Code Starts
#include <iostream>
using namespace std;
//Driver Code Ends


bool isInleaveRec(string &s1, string &s2, string &s3, int i, int j){

    int k = i + j;

    // If all strings are fully traversed
    if (i == s1.size() && j == s2.size() && k == s3.size())
        return true;
        
    bool a = (i < s1.size()) && (s3[k] == s1[i]) 
    && isInleaveRec(s1, s2, s3, i + 1, j);
    
    bool b = (j < s2.size()) && (s3[k] == s2[j]) 
    && isInleaveRec(s1, s2, s3, i, j + 1);
    
    // If any of the above two possibilities return true
    // otherwise return false.
    return a || b;
}

bool isInterleave(string &s1, string &s2, string &s3)
{
    if (s1.size() + s2.size() != s3.size())
        return false;

    return isInleaveRec(s1, s2, s3, 0, 0);
}


//Driver Code Starts
int main()
{
    string s1 = "AAB";
    string s2 = "AAC";
    string s3 = "AAAABC";
    cout << (isInterleave(s1, s2, s3) ? "true" : "false") << endl;
    return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
class GFG {
//Driver Code Ends


    static boolean isInleaveRec(String s1, String s2, String s3, int i, int j) {

        int k = i + j;

        // If all strings are fully traversed
        if (i == s1.length() && j == s2.length() && k == s3.length())
            return true;

        boolean a = (i < s1.length()) && (s3.charAt(k) == s1.charAt(i))
                    && isInleaveRec(s1, s2, s3, i + 1, j);
        
        boolean b = (j < s2.length()) && (s3.charAt(k) == s2.charAt(j))
                    && isInleaveRec(s1, s2, s3, i, j + 1);
        
        // If any of the above two possibilities return true
        // otherwise return false.
        return a || b;
    }

    static boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length() + s2.length() != s3.length())
            return false;

        return isInleaveRec(s1, s2, s3, 0, 0);
    }


//Driver Code Starts
    public static void main(String[] args) {
        String s1 = "AAB";
        String s2 = "AAC";
        String s3 = "AAAABC";
        System.out.println(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
Python
def isInleaveRec(s1, s2, s3, i, j):
    k = i + j

    # If all strings are fully traversed
    if i == len(s1) and j == len(s2) and k == len(s3):
        return True

    a = (i < len(s1)) and (s3[k] == s1[i]) and isInleaveRec(s1, s2, s3, i + 1, j)
    b = (j < len(s2)) and (s3[k] == s2[j]) and isInleaveRec(s1, s2, s3, i, j + 1)

    # If any of the above two possibilities return true
    # otherwise return false.
    return a or b


def isInterleave(s1, s2, s3):
    if len(s1) + len(s2) != len(s3):
        return False
    return isInleaveRec(s1, s2, s3, 0, 0)
    


#Driver Code Starts
if __name__ == "__main__":
    s1 = "AAB"
    s2 = "AAC"
    s3 = "AAAABC"
    print("true" if isInterleave(s1, s2, s3) else "false")

#Driver Code Ends
C#
//Driver Code Starts
using System;

class GFG {
//Driver Code Ends

    static bool isInleaveRec(string s1, string s2, string s3, int i, int j) {

        int k = i + j;

        // If all strings are fully traversed
        if (i == s1.Length && j == s2.Length && k == s3.Length)
            return true;

        bool a = (i < s1.Length) && (s3[k] == s1[i])
                  && isInleaveRec(s1, s2, s3, i + 1, j);
        
        bool b = (j < s2.Length) && (s3[k] == s2[j])
                  && isInleaveRec(s1, s2, s3, i, j + 1);
        
        // If any of the above two possibilities return true
        // otherwise return false.
        return a || b;
    }

    static bool isInterleave(string s1, string s2, string s3) {
        if (s1.Length + s2.Length != s3.Length)
            return false;

        return isInleaveRec(s1, s2, s3, 0, 0);
    }


//Driver Code Starts
    static void Main() {
        string s1 = "AAB";
        string s2 = "AAC";
        string s3 = "AAAABC";
        Console.WriteLine(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
JavaScript
function isInleaveRec(s1, s2, s3, i, j) {
    let k = i + j;

    // If all strings are fully traversed
    if (i === s1.length && j === s2.length && k === s3.length)
        return true;

    let a = (i < s1.length) && (s3[k] === s1[i]) &&
            isInleaveRec(s1, s2, s3, i + 1, j);

    let b = (j < s2.length) && (s3[k] === s2[j]) &&
            isInleaveRec(s1, s2, s3, i, j + 1);

    // If any of the above two possibilities return true
    // otherwise return false.
    return a || b;
}

function isInterleave(s1, s2, s3) {
    if (s1.length + s2.length !== s3.length)
        return false;

    return isInleaveRec(s1, s2, s3, 0, 0);
}


//Driver Code Starts
//Driver Code
let s1 = "AAB";
let s2 = "AAC";
let s3 = "AAAABC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");

//Driver Code Ends

Output
true

[Better Approach 1] Using Top-Down(Memoization) DP - O(m*n) Time and O(n*m) Space

In the previous recursive approach, we explored every possible way to form s3 using s1 and s2.
At each step, we had two choices - take a character from s1 or take it from s2. However, while exploring all combinations, we end up solving the same subproblems multiple times. To avoid this repetition, we can store the results of already computed subproblems called Memoization.

The idea is simple, we create a 2D DP table of size (m+1) x (n+1), where dp[i][j] represents whether the substring s3[i+j..n+m-1] can be formed by interleaving s1[i ..n-1] and s2[j..m-1].
For any subproblem (i, j), if the result is already stored in dp[i][j], we return it directly. Otherwise, we compute it recursively and store the result in the table.

This avoids recomputation of overlapping subproblems and improves the efficiency of the solution from exponential to polynomial time.

C++
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends


// Recursive function with memoization 
bool isInleaveRec(string &s1, string &s2, string &s3, int i, int j, vector<vector<int>> &dp)
{
    int k = i + j;
    int m = s1.size(), n = s2.size();

    // Base case
    if (i == m && j == n && k == s3.size())
        return true;

    if (dp[i][j] != -1)
        return dp[i][j];

    //If next character of s1 matches with s3
    bool a = (i < m && s1[i] == s3[k]) && isInleaveRec(s1, s2, s3, i + 1, j, dp);

    // If next character of s2 matches with s3
    bool b = (j < n && s2[j] == s3[k]) && isInleaveRec(s1, s2, s3, i, j + 1, dp);

    // Store the result before returning
    return dp[i][j] = a || b;
}

bool isInterleave(string &s1, string &s2, string &s3)
{
    int m = s1.size(), n = s2.size();
    if (m + n != s3.size())
        return false;

    vector<vector<int>> dp(m + 1, vector<int>(n + 1, -1));
    return isInleaveRec(s1, s2, s3, 0, 0, dp);
}


//Driver Code Starts
int main()
{
    string s1 = "AAB";
    string s2 = "AAC";
    string s3 = "AAAABC";
    cout << (isInterleave(s1, s2, s3) ? "true" : "false") << endl;
    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
import java.util.Arrays;

public class GFG {
//Driver Code Ends


    // Recursive function with memoization 
    static boolean isInleaveRec(String s1, String s2, String s3, int i, int j, int[][] dp) {
        int k = i + j;
        int m = s1.length(), n = s2.length();

        // Base case
        if (i == m && j == n && k == s3.length())
            return true;

        if (dp[i][j] != -1)
            return dp[i][j] == 1;

        // If next character of s1 matches with s3
        boolean a = (i < m && s1.charAt(i) == 
        s3.charAt(k)) && isInleaveRec(s1, s2, s3, i + 1, j, dp);

        // If next character of s2 matches with s3
        boolean b = (j < n && s2.charAt(j) == 
        s3.charAt(k)) && isInleaveRec(s1, s2, s3, i, j + 1, dp);

        // Store the result before returning
        dp[i][j] = (a || b) ? 1 : 0;
        return a || b;
    }

    static boolean isInterleave(String s1, String s2, String s3) {
        int m = s1.length(), n = s2.length();
        if (m + n != s3.length())
            return false;

        int[][] dp = new int[m + 1][n + 1];
        for (int[] row : dp) Arrays.fill(row, -1);

        return isInleaveRec(s1, s2, s3, 0, 0, dp);
    }


//Driver Code Starts
    public static void main(String[] args) {
        String s1 = "AAB";
        String s2 = "AAC";
        String s3 = "AAAABC";
        System.out.println(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
Python
# Recursive function with memoization 
def isInleaveRec(s1, s2, s3, i, j, dp):
    k = i + j
    m, n = len(s1), len(s2)

    # Base case
    if i == m and j == n and k == len(s3):
        return True

    if dp[i][j] != -1:
        return dp[i][j]

    # If next character of s1 matches with s3
    a = (i < m and s1[i] == s3[k]) and isInleaveRec(s1, s2, s3, i + 1, j, dp)

    # If next character of s2 matches with s3
    b = (j < n and s2[j] == s3[k]) and isInleaveRec(s1, s2, s3, i, j + 1, dp)

    # Store the result before returning
    dp[i][j] = a or b
    return dp[i][j]

def isInterleave(s1, s2, s3):
    m, n = len(s1), len(s2)
    if m + n != len(s3):
        return False

    dp = [[-1 for _ in range(n + 1)] for _ in range(m + 1)]
    return isInleaveRec(s1, s2, s3, 0, 0, dp)


#Driver Code Starts

if __name__ == "__main__":
    s1 = "AAB"
    s2 = "AAC"
    s3 = "AAAABC"
    print("true" if isInterleave(s1, s2, s3) else "false")

#Driver Code Ends
C#
//Driver Code Starts
using System;
using System.Collections.Generic;

class GFG
{
//Driver Code Ends

    // Recursive function with memoization 
    static bool isInleaveRec(string s1, string s2, string s3, int i, int j, int[,] dp)
    {
        int k = i + j;
        int m = s1.Length, n = s2.Length;

        // Base case
        if (i == m && j == n && k == s3.Length)
            return true;

        if (dp[i, j] != -1)
            return dp[i, j] == 1;

        // If next character of s1 matches with s3
        bool a = (i < m && s1[i] == s3[k]) && isInleaveRec(s1, s2, s3, i + 1, j, dp);

        // If next character of s2 matches with s3
        bool b = (j < n && s2[j] == s3[k]) && isInleaveRec(s1, s2, s3, i, j + 1, dp);

        // Store the result before returning
        dp[i, j] = (a || b) ? 1 : 0;
        return a || b;
    }

    static bool isInterleave(string s1, string s2, string s3)
    {
        int m = s1.Length, n = s2.Length;
        if (m + n != s3.Length)
            return false;

        int[,] dp = new int[m + 1, n + 1];
        for (int x = 0; x <= m; x++)
            for (int y = 0; y <= n; y++)
                dp[x, y] = -1;

        return isInleaveRec(s1, s2, s3, 0, 0, dp);
    }


//Driver Code Starts
    static void Main()
    {
        string s1 = "AAB";
        string s2 = "AAC";
        string s3 = "AAAABC";
        Console.WriteLine(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
JavaScript
// Recursive function with memoization 
function isInleaveRec(s1, s2, s3, i, j, dp) {
    let k = i + j;
    let m = s1.length, n = s2.length;

    // Base case
    if (i === m && j === n && k === s3.length)
        return true;

    if (dp[i][j] !== -1)
        return dp[i][j];

    // If next character of s1 matches with s3
    let a = (i < m && s1[i] === s3[k]) && isInleaveRec(s1, s2, s3, i + 1, j, dp);

    // If next character of s2 matches with s3
    let b = (j < n && s2[j] === s3[k]) && isInleaveRec(s1, s2, s3, i, j + 1, dp);

    // Store the result before returning
    dp[i][j] = a || b;
    return dp[i][j];
}

function isInterleave(s1, s2, s3) {
    let m = s1.length, n = s2.length;
    if (m + n !== s3.length)
        return false;

    let dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(-1));
    return isInleaveRec(s1, s2, s3, 0, 0, dp);
}


// Driver code
//Driver Code Starts
let s1 = "AAB";
let s2 = "AAC";
let s3 = "AAAABC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");

//Driver Code Ends

Output
true

[Better Approach 2] Using Bottom-Up DP - O(m*n) Time and O(m*n) Space

In the previous recursive and memoization approaches, we used recursion to explore all possibilities and stored results to avoid recomputation. Now, to make it more efficient, we can build the same logic iteratively from bottom up using a DP table. This helps us avoid the overhead of recursion and makes it easier to understand.

We create a 2D dp array of size (m + 1) x (n + 1). First, we define some base cases to start iteration: dp[0][0] = true because empty s1 and empty s2 can form empty s3 and fill first row and first col by using two conditions:

  • If s1 is empty, then we can form s3 only using characters from s2, so we check if s2[j - 1] == s3[j - 1].
  • If s2 is empty, then we can form s3 only using characters from s1, s1[i - 1] == s3[i - 1].

After that, we iterate through both strings and fill the dp table. For each dp[i][j], we have two choices: Take the current character from s1 if it matches the current character of s3 or take the current character from s2 if it matches the current character of s3. Finally, after filling the entire table, dp[m][n] will tell us whether s3 can be formed by interleaving s1 and s2.

C++
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends


bool isInterleave(string &s1, string &s2, string &s3)
{
    int m = s1.size(), n = s2.size();

    // s3 can only be formed if total lengths match
    if (m + n != s3.size())
        return false;

    vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
    dp[0][0] = true; 

    // Fill first row (s1 is empty)
    for (int j = 1; j <= n; j++)
        dp[0][j] = (s2[j - 1] == s3[j - 1]) && dp[0][j - 1];

    // Fill first column (s2 is empty)
    for (int i = 1; i <= m; i++)
        dp[i][0] = (s1[i - 1] == s3[i - 1]) && dp[i - 1][0];

    // Fill the rest of dp table
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            int k = i + j - 1;
            dp[i][j] = (s1[i - 1] == s3[k] && dp[i - 1][j]) ||
                       (s2[j - 1] == s3[k] && dp[i][j - 1]);
        }
    }

    return dp[m][n];
}


//Driver Code Starts
int main()
{
    string s1 = "AAB";
    string s2 = "AAC";
    string s3 = "AAAABC";

    cout << (isInterleave(s1, s2, s3) ? "true" : "false") << endl;
    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
import java.util.Arrays;

public class GFG{
//Driver Code Ends


    static boolean isInterleave(String s1, String s2, String s3) {
        int m = s1.length(), n = s2.length();

        // s3 can only be formed if total lengths match
        if (m + n != s3.length())
            return false;

        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;

        // Fill first row (s1 is empty)
        for (int j = 1; j <= n; j++)
            dp[0][j] = (s2.charAt(j - 1) == s3.charAt(j - 1)) && dp[0][j - 1];

        // Fill first column (s2 is empty)
        for (int i = 1; i <= m; i++)
            dp[i][0] = (s1.charAt(i - 1) == s3.charAt(i - 1)) && dp[i - 1][0];

        // Fill the rest of dp table
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                int k = i + j - 1;
                dp[i][j] = (s1.charAt(i - 1) == s3.charAt(k) && dp[i - 1][j]) ||
                           (s2.charAt(j - 1) == s3.charAt(k) && dp[i][j - 1]);
            }
        }

        return dp[m][n];
    }


//Driver Code Starts
    public static void main(String[] args) {
        String s1 = "AAB";
        String s2 = "AAC";
        String s3 = "AAAABC";

        System.out.println(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
Python
def isInterleave(s1, s2, s3):
    m, n = len(s1), len(s2)

    # s3 can only be formed if total lengths match
    if m + n != len(s3):
        return False

    dp = [[False] * (n + 1) for _ in range(m + 1)]
    dp[0][0] = True

    # Fill first row (s1 is empty)
    for j in range(1, n + 1):
        dp[0][j] = (s2[j - 1] == s3[j - 1]) and dp[0][j - 1]

    # Fill first column (s2 is empty)
    for i in range(1, m + 1):
        dp[i][0] = (s1[i - 1] == s3[i - 1]) and dp[i - 1][0]

    # Fill the rest of dp table
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            k = i + j - 1
            dp[i][j] = ((s1[i - 1] == s3[k] and dp[i - 1][j]) or
                        (s2[j - 1] == s3[k] and dp[i][j - 1]))

    return dp[m][n]

if __name__ == "__main__":
    s1 = "AAB"
    s2 = "AAC"
    s3 = "AAAABC"
    print("true" if isInterleave(s1, s2, s3) else "false")
C#
//Driver Code Starts
using System;

class GFG
{
//Driver Code Ends

    static bool isInterleave(string s1, string s2, string s3)
    {
        int m = s1.Length, n = s2.Length;

        // s3 can only be formed if total lengths match
        if (m + n != s3.Length)
            return false;

        bool[,] dp = new bool[m + 1, n + 1];
        dp[0, 0] = true;

        // Fill first row (s1 is empty)
        for (int j = 1; j <= n; j++)
            dp[0, j] = (s2[j - 1] == s3[j - 1]) && dp[0, j - 1];

        // Fill first column (s2 is empty)
        for (int i = 1; i <= m; i++)
            dp[i, 0] = (s1[i - 1] == s3[i - 1]) && dp[i - 1, 0];

        // Fill the rest of dp table
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                int k = i + j - 1;
                dp[i, j] = (s1[i - 1] == s3[k] && dp[i - 1, j]) ||
                           (s2[j - 1] == s3[k] && dp[i, j - 1]);
            }
        }

        return dp[m, n];
    }


//Driver Code Starts
    static void Main()
    {
        string s1 = "AAB";
        string s2 = "AAC";
        string s3 = "AAAABC";

        Console.WriteLine(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
JavaScript
function isInterleave(s1, s2, s3) {
    const m = s1.length, n = s2.length;

    // s3 can only be formed if total lengths match
    if (m + n !== s3.length) return false;

    const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(false));
    dp[0][0] = true;

    // Fill first row (s1 is empty)
    for (let j = 1; j <= n; j++)
        dp[0][j] = (s2[j - 1] === s3[j - 1]) && dp[0][j - 1];

    // Fill first column (s2 is empty)
    for (let i = 1; i <= m; i++)
        dp[i][0] = (s1[i - 1] === s3[i - 1]) && dp[i - 1][0];

    // Fill the rest of dp table
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            const k = i + j - 1;
            dp[i][j] = (s1[i - 1] === s3[k] && dp[i - 1][j]) ||
                       (s2[j - 1] === s3[k] && dp[i][j - 1]);
        }
    }

    return dp[m][n];
}


//Driver Code
//Driver Code Starts
const s1 = "AAB";
const s2 = "AAC";
const s3 = "AAAABC";

console.log(isInterleave(s1, s2, s3) ? "true" : "false");

//Driver Code Ends

Output
true

[Expected Approach] Space-Optimized DP - O(m*n) Time and O(m) Space

In the previous DP approach, we used a 2D array dp[m+1][n+1] to store all intermediate results. But if we look carefully, each row i only depends on the previous row i-1 and the current row we are computing. This means we don’t really need the whole 2D array. We can reduce the space from O(m×n) to O(2×(n+1)) by using just two rows: prev and curr.

Here, prev[j] corresponds to dp[i-1][j] in the 2D table, and curr[j-1] corresponds to dp[i][j-1]. So conceptually, we are doing the exact same computation as the 2D DP, but we are storing much less data. This makes the solution more space-efficient while keeping the logic simple and easy to follow.

C++
//Driver Code Starts
#include <iostream>
#include<vector>
using namespace std;
//Driver Code Ends


bool isInterleave(string &s1, string &s2, string &s3)
{
    // If lengths don't match, return false
    if (s1.size() + s2.size() != s3.size())
        return false;

    int n = s1.size(), m = s2.size();

    // Two rows for DP
    vector<bool> prev(m + 1, false), curr(m + 1, false);

    // Base case
    prev[0] = true;

    // Fill first row (s1 empty)
    for (int j = 1; j <= m; ++j)
        prev[j] = prev[j - 1] && (s2[j - 1] == s3[j - 1]);

    // Fill the DP rows
    for (int i = 1; i <= n; ++i)
    {
        // first column
        curr[0] = prev[0] && (s1[i - 1] == s3[i - 1]); 

        for (int j = 1; j <= m; ++j)
        {
            int k = i + j;
            curr[j] = (prev[j] && s1[i - 1] == s3[k - 1]) || 
            (curr[j - 1] && s2[j - 1] == s3[k - 1]);
        }
        
        // move current row to previous
        prev = curr;
    }

    return prev[m];
}


//Driver Code Starts
int main()
{
    string s1 = "AAB";
    string s2 = "AAC";
    string s3 = "AAABAC";
    cout << (isInterleave(s1, s2, s3) ? "true" : "false");
    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
import java.util.Arrays;

public class GFG {
//Driver Code Ends


    static boolean isInterleave(String s1, String s2, String s3) {
        
        // If lengths don't match, return false
        if (s1.length() + s2.length() != s3.length())
            return false;

        int n = s1.length(), m = s2.length();

        // Two rows for DP
        boolean[] prev = new boolean[m + 1];
        boolean[] curr = new boolean[m + 1];

        // Base case
        prev[0] = true;

        // Fill first row (s1 empty)
        for (int j = 1; j <= m; j++)
            prev[j] = prev[j - 1] && (s2.charAt(j - 1) == s3.charAt(j - 1));

        // Fill the DP rows
        for (int i = 1; i <= n; i++) {
            // first column
            curr[0] = prev[0] && (s1.charAt(i - 1) == s3.charAt(i - 1));

            for (int j = 1; j <= m; j++) {
                int k = i + j;
                curr[j] = (prev[j] && s1.charAt(i - 1) == s3.charAt(k - 1)) ||
                          (curr[j - 1] && s2.charAt(j - 1) == s3.charAt(k - 1));
            }

            // move current row to previous
            prev = curr.clone();
        }

        return prev[m];
    }


//Driver Code Starts
    public static void main(String[] args) {
        String s1 = "AAB";
        String s2 = "AAC";
        String s3 = "AAABAC";
        System.out.println(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
Python
def isInterleave(s1, s2, s3):
    
    # If lengths don't match, return false
    if len(s1) + len(s2) != len(s3):
        return False

    n, m = len(s1), len(s2)

    # Two rows for DP
    prev = [False] * (m + 1)
    curr = [False] * (m + 1)

    # Base case
    prev[0] = True

    # Fill first row (s1 empty)
    for j in range(1, m + 1):
        prev[j] = prev[j - 1] and s2[j - 1] == s3[j - 1]

    # Fill the DP rows
    for i in range(1, n + 1):
        # first column
        curr[0] = prev[0] and s1[i - 1] == s3[i - 1]

        for j in range(1, m + 1):
            k = i + j
            curr[j] = (prev[j] and s1[i - 1] == s3[k - 1]) or \
                      (curr[j - 1] and s2[j - 1] == s3[k - 1])

        # move current row to previous
        prev = curr[:]

    return prev[m]
    

    
#Driver Code Starts
if __name__ == "__main__":
    s1 = "AAB"
    s2 = "AAC"
    s3 = "AAABAC"
    print("true" if isInterleave(s1, s2, s3) else "false")

#Driver Code Ends
C#
//Driver Code Starts
using System;

class GFG
{
//Driver Code Ends

    static bool isInterleave(string s1, string s2, string s3)
    {
        // If lengths don't match, return false
        if (s1.Length + s2.Length != s3.Length)
            return false;

        int n = s1.Length, m = s2.Length;

        // Two rows for DP
        bool[] prev = new bool[m + 1];
        bool[] curr = new bool[m + 1];

        // Base case
        prev[0] = true;

        // Fill first row (s1 empty)
        for (int j = 1; j <= m; j++)
            prev[j] = prev[j - 1] && (s2[j - 1] == s3[j - 1]);

        // Fill the DP rows
        for (int i = 1; i <= n; i++)
        {
            // first column
            curr[0] = prev[0] && (s1[i - 1] == s3[i - 1]);

            for (int j = 1; j <= m; j++)
            {
                int k = i + j;
                curr[j] = (prev[j] && s1[i - 1] == s3[k - 1]) ||
                          (curr[j - 1] && s2[j - 1] == s3[k - 1]);
            }

            // move current row to previous
            Array.Copy(curr, prev, m + 1);
        }

        return prev[m];
    }


//Driver Code Starts
    static void Main()
    {
        string s1 = "AAB";
        string s2 = "AAC";
        string s3 = "AAABAC";
        Console.WriteLine(isInterleave(s1, s2, s3) ? "true" : "false");
    }
}

//Driver Code Ends
JavaScript
function isInterleave(s1, s2, s3) {
    
    // If lengths don't match, return false
    if (s1.length + s2.length !== s3.length) return false;

    let n = s1.length, m = s2.length;

    // Two rows for DP
    let prev = new Array(m + 1).fill(false);
    let curr = new Array(m + 1).fill(false);

    // Base case
    prev[0] = true;

    // Fill first row (s1 empty)
    for (let j = 1; j <= m; j++) {
        prev[j] = prev[j - 1] && (s2[j - 1] === s3[j - 1]);
    }

    // Fill the DP rows
    for (let i = 1; i <= n; i++) {
        // first column
        curr[0] = prev[0] && (s1[i - 1] === s3[i - 1]);

        for (let j = 1; j <= m; j++) {
            let k = i + j;
            curr[j] = (prev[j] && s1[i - 1] === s3[k - 1]) ||
                      (curr[j - 1] && s2[j - 1] === s3[k - 1]);
        }

        // move current row to previous
        prev = [...curr];
    }

    return prev[m];
}


// Driver Code
//Driver Code Starts
let s1 = "AAB";
let s2 = "AAC";
let s3 = "AAABAC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");

//Driver Code Ends

Output
true

Check whether a given string is an interleaving of two other given strings

Explore