Check if a String is Interleaving of Other Two
Last Updated :
08 Nov, 2025
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
[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
[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
[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
Check whether a given string is an interleaving of two other given strings
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem