Check if a String is Interleaving of Other Two (original) (raw)

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:

**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.

Table of Content

[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.

C++ `

//Driver Code Starts #include 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

`

[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 #include using namespace std; //Driver Code Ends

// Recursive function with memoization bool isInleaveRec(string &s1, string &s2, string &s3, int i, int j, vector<vector> &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

`

[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:

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 #include 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

`

[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 #include 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

`