Check if a String is Interleaving of Other Two
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
ands2
while preserving their relative order. - Characters from
s1
ands2
appear ins3
in the same order as in their original strings. - The length of
s3
equals the combined length ofs1
ands2
.
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 = “AB”, s2 = “C”, s3 = “ACB”,
Output: true
Explanation: s3 has all characters of s1 and s2 and retains order of characters of s1.
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) Space
The main idea is to recursively check whether s3 can be formed by choosing characters from s1 and s2, ensuring we maintain the correct order. To do so, initialise three variable i, j, and k to store the index of string s1, s2, and s3 respectively. 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.
// Cpp program to check if Check if a String is
// Interleaving of Other Two using recursion
#include <iostream>
using namespace std;
// i amnd j are indexes in s1 and s2 respectively
bool isILRec(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;
// If any of the above mentioned two
// possibilities then return true
// otherwise return false.
bool a = (i < s1.size()) && (s3[k] == s1[i]) && isILRec(s1, s2, s3, i + 1, j);
bool b = (j < s2.size()) && (s3[k] == s2[j]) && isILRec(s1, s2, s3, i, j + 1);
return a || b;
}
bool isInterleave(string &s1, string &s2, string &s3)
{
// A basic condition that must be ensured
if (s1.size() + s2.size() != s3.size())
return false;
return isILRec(s1, s2, s3, 0, 0);
}
int main()
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
cout << (isInterleave(s1, s2, s3) ? "true" : "false") << endl;
return 0;
}
// Java program to check if Check if a String is
// Interleaving of Other Two using recursion
class GfG {
// i and j are indexes in s1 and s2 respectively
static boolean isILRec(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;
// If any of the above mentioned two
// possibilities then return true
// otherwise return false.
boolean a = (i < s1.length())
&& (s3.charAt(k) == s1.charAt(i))
&& isILRec(s1, s2, s3, i + 1, j);
boolean b = (j < s2.length())
&& (s3.charAt(k) == s2.charAt(j))
&& isILRec(s1, s2, s3, i, j + 1);
return a || b;
}
static boolean isInterleave(String s1, String s2,
String s3)
{
// A basic condition that must be ensured
if (s1.length() + s2.length() != s3.length())
return false;
return isILRec(s1, s2, s3, 0, 0);
}
public static void main(String[] args)
{
String s1 = "AAB";
String s2 = "AAC";
String s3 = "AAAABC";
System.out.println(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
# Python program to check if Check if a String is
# Interleaving of Other Two using recursion
def isILRec(s1, s2, s3, i, j):
# i and j are indexes in s1 and s2 respectively
k = i + j
# If all strings are fully traversed
if i == len(s1) and j == len(s2) and k == len(s3):
return True
# If any of the above mentioned two
# possibilities then return true
# otherwise return false.
a = (i < len(s1)) and (s3[k] == s1[i]) and isILRec(s1, s2, s3, i + 1, j)
b = (j < len(s2)) and (s3[k] == s2[j]) and isILRec(s1, s2, s3, i, j + 1)
return a or b
def isInterleave(s1, s2, s3):
# A basic condition that must be ensured
if len(s1) + len(s2) != len(s3):
return False
return isILRec(s1, s2, s3, 0, 0)
if __name__ == "__main__":
s1 = "AAB"
s2 = "AAC"
s3 = "AAAABC"
print("true" if isInterleave(s1, s2, s3) else "false")
// C# program to check if Check if a String is
// Interleaving of Other Two using recursion
using System;
class GfG {
// i and j are indexes in s1 and s2 respectively
static bool isILRec(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;
// If any of the above mentioned two
// possibilities then return true
// otherwise return false.
bool a = (i < s1.Length) && (s3[k] == s1[i])
&& isILRec(s1, s2, s3, i + 1, j);
bool b = (j < s2.Length) && (s3[k] == s2[j])
&& isILRec(s1, s2, s3, i, j + 1);
return a || b;
}
static bool isInterleave(string s1, string s2,
string s3)
{
// A basic condition that must be ensured
if (s1.Length + s2.Length != s3.Length)
return false;
return isILRec(s1, s2, s3, 0, 0);
}
static void Main(string[] args)
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
Console.WriteLine(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
// JavaScript program to check if Check if a String is
// Interleaving of Other Two using recursion
function isILRec(s1, s2, s3, i, j)
{
// i and j are indexes in s1 and s2 respectively
let k = i + j;
// If all strings are fully traversed
if (i === s1.length && j === s2.length
&& k === s3.length)
return true;
// If any of the above mentioned two
// possibilities then return true
// otherwise return false.
let a = (i < s1.length) && (s3[k] === s1[i])
&& isILRec(s1, s2, s3, i + 1, j);
let b = (j < s2.length) && (s3[k] === s2[j])
&& isILRec(s1, s2, s3, i, j + 1);
return a || b;
}
function isInterleave(s1, s2, s3)
{
// A basic condition that must be ensured
if (s1.length + s2.length !== s3.length)
return false;
return isILRec(s1, s2, s3, 0, 0);
}
// Driver Code
let s1 = "AAB";
let s2 = "AAC";
let s3 = "AAAABC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");
Output
true
[Better Approach 1] Using Top-Down DP – O(m*n) Time and O(n*m) Space
The above recursive solution certainly has many overlapping sub-problems. For example, if we consider s1 = “AAB”, s2 = “AAC” and s3 = “AAAABC” 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. Below is a memoization based solution that creates a 2D memo array.
We optimize the recursive approach using memoization to avoid redundant calculations.
We track indices i and j in s1 and s2, respectively, ensuring that characters match s3 at index k = i + j. If either s1[i] or s2[j] matches s3[k], we recursively move forward while storing results in a memo table to prevent recomputation.
The base case ensures that when all strings are fully traversed, we return true. This approach significantly reduces the time complexity compared to plain recursion.
Steps to implement the above idea:
- Check if s3 length is equal to s1 + s2, return false if not.
- Create a (m+1) x (n+1) table memo[][] with -1 to store results. The value of memo[i][j] is going to be 1 if s3[0..i + j-1] is an interleaving of s1[0..i-1] and s2[0..j-1], else 0.
- If memo[i][j] is not -1, return the stored result to avoid recomputation.
- Try both possibilities (matching s1[i] or s2[j] with s3[k]) and store the result in memo[i][j].
- Return true if all strings are fully traversed, otherwise return false.
// C++ program to check if Check if a String is
// Interleaving of Other Two using memoization
#include <bits/stdc++.h>
using namespace std;
bool isILRec(string &s1, string &s2, string &s3, int i, int j, vector<vector<int>> &memo)
{
int k = i + j;
int m = s1.size(), n = s2.size();
// Base case: If all strings are fully traversed
if (i == m && j == n && k == s3.size())
return true;
// If we have already solved this subproblem,
// return the stored result
if (memo[i][j] != -1)
{
return memo[i][j];
}
// Check if next characcter of s1 maatchs with
// with the next one of s3
bool a = (i < m && s1[i] == s3[k]) && isILRec(s1, s2, s3, i + 1, j, memo);
// Check if next characcter of s2 maatchs with
// with the next one of s3
bool b = (j < n && s2[j] == s3[k]) && isILRec(s1, s2, s3, i, j + 1, memo);
return memo[i][j] = a || b;
}
bool isInterleave(string &s1, string &s2, string &s3)
{
int m = s1.size(), n = s2.size();
// A basic condition that must be ensured
if (m + n != s3.size())
return false;
// Intiialize memo with -1 and make Recursive function call
vector<vector<int>> memo(m + 1, vector<int>(n + 1, -1));
return isILRec(s1, s2, s3, 0, 0, memo);
}
int main()
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
cout << (isInterleave(s1, s2, s3) ? "true" : "false") << endl;
return 0;
}
// Java program to check if Check if a String is
// Interleaving of Other Two using memoization
import java.util.Arrays;
class GfG {
// i and j are indexes in s1 and s2 respectively
static boolean isILRec(String s1, String s2, String s3,
int i, int j, int[][] memo)
{
int k = i + j;
int m = s1.length();
int n = s2.length();
// Base case: If all strings are fully traversed
if (i == m && j == n && k == s3.length())
return true;
// If we have already solved this subproblem,
// return the stored result
if (memo[i][j] != -1) {
return memo[i][j] == 1;
}
// Check if next character of s1 matches with
// with the next one of s3
boolean a = false;
if (i < m && s1.charAt(i) == s3.charAt(k)) {
a = isILRec(s1, s2, s3, i + 1, j, memo);
}
// Check if next character of s2 matches with
// with the next one of s3
boolean b = false;
if (j < n && s2.charAt(j) == s3.charAt(k)) {
b = isILRec(s1, s2, s3, i, j + 1, memo);
}
memo[i][j] = a || b ? 1 : 0;
return a || b;
}
static boolean isInterleave(String s1, String s2,
String s3)
{
int m = s1.length();
int n = s2.length();
// A basic condition that must be ensured
if (m + n != s3.length())
return false;
// Initialize memo with -1 and make Recursive
// function call
int[][] memo = new int[m + 1][n + 1];
for (int[] row : memo)
Arrays.fill(row, -1);
return isILRec(s1, s2, s3, 0, 0, memo);
}
public static void main(String[] args)
{
String s1 = "AAB";
String s2 = "AAC";
String s3 = "AAAABC";
System.out.println(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
# Python program to check if Check if a String is
# Interleaving of Other Two using memoization
def isILRec(s1, s2, s3, i, j, memo):
# i and j are indexes in s1 and s2 respectively
k = i + j
m = len(s1)
n = len(s2)
# Base case: If all strings are fully traversed
if i == m and j == n and k == len(s3):
return True
# If we have already solved this subproblem,
# return the stored result
if memo[i][j] != -1:
return memo[i][j] == 1
# Check if next character of s1 matches with
# with the next one of s3
a = False
if i < m and s1[i] == s3[k]:
a = isILRec(s1, s2, s3, i + 1, j, memo)
# Check if next character of s2 matches with
# with the next one of s3
b = False
if j < n and s2[j] == s3[k]:
b = isILRec(s1, s2, s3, i, j + 1, memo)
memo[i][j] = 1 if a or b else 0
return a or b
def isInterleave(s1, s2, s3):
# A basic condition that must be ensured
m = len(s1)
n = len(s2)
if m + n != len(s3):
return False
# Initialize memo with -1 and make Recursive function call
memo = [[-1 for _ in range(n + 1)] for _ in range(m + 1)]
return isILRec(s1, s2, s3, 0, 0, memo)
if __name__ == "__main__":
s1 = "AAB"
s2 = "AAC"
s3 = "AAAABC"
print("true" if isInterleave(s1, s2, s3) else "false")
// C# program to check if Check if a String is
// Interleaving of Other Two using memoization
using System;
class GfG {
// i and j are indexes in s1 and s2 respectively
static bool isILRec(string s1, string s2, string s3,
int i, int j, int[, ] memo)
{
int k = i + j;
int m = s1.Length;
int n = s2.Length;
// Base case: If all strings are fully traversed
if (i == m && j == n && k == s3.Length)
return true;
// If we have already solved this subproblem,
// return the stored result
if (memo[i, j] != -1)
return memo[i, j] == 1;
// Check if next character of s1 matches with
// with the next one of s3
bool a = false;
if (i < m && s1[i] == s3[k])
a = isILRec(s1, s2, s3, i + 1, j, memo);
// Check if next character of s2 matches with
// with the next one of s3
bool b = false;
if (j < n && s2[j] == s3[k])
b = isILRec(s1, s2, s3, i, j + 1, memo);
memo[i, j] = (a || b) ? 1 : 0;
return a || b;
}
static bool isInterleave(string s1, string s2,
string s3)
{
int m = s1.Length;
int n = s2.Length;
// A basic condition that must be ensured
if (m + n != s3.Length)
return false;
// Initialize memo with -1 and make Recursive
// function call
int[, ] memo = new int[m + 1, n + 1];
for (int i = 0; i <= m; i++)
for (int j = 0; j <= n; j++)
memo[i, j] = -1;
return isILRec(s1, s2, s3, 0, 0, memo);
}
static void Main(string[] args)
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
Console.WriteLine(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
// Javascript program to check if Check if a String is
// Interleaving of Other Two using memoization
function isILRec(s1, s2, s3, i, j, memo)
{
// i and j are indexes in s1 and s2 respectively
let k = i + j;
let m = s1.length;
let n = s2.length;
// Base case: If all strings are fully traversed
if (i === m && j === n && k === s3.length)
return true;
// If we have already solved this subproblem,
// return the stored result
if (memo[i][j] !== -1) {
return memo[i][j] === 1;
}
// Check if next character of s1 matches with
// with the next one of s3
let a = false;
if (i < m && s1[i] === s3[k]) {
a = isILRec(s1, s2, s3, i + 1, j, memo);
}
// Check if next character of s2 matches with
// with the next one of s3
let b = false;
if (j < n && s2[j] === s3[k]) {
b = isILRec(s1, s2, s3, i, j + 1, memo);
}
memo[i][j] = (a || b) ? 1 : 0;
return a || b;
}
function isInterleave(s1, s2, s3)
{
// A basic condition that must be ensured
let m = s1.length;
let n = s2.length;
if (m + n !== s3.length)
return false;
// Initialize memo with -1 and make Recursive function
// call
let memo = Array(m + 1).fill(null).map(
() => Array(n + 1).fill(-1));
return isILRec(s1, s2, s3, 0, 0, memo);
}
// Driver Code
let s1 = "AAB";
let s2 = "AAC";
let s3 = "AAAABC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");
Output
true
[Better Approach 2] Using Bottom-Up DP – O(m*n) Time and O(m*n) Space
Step by Step implementation:
- The main idea is to create a 2D DP table dp[m+1][n+1] , where dp[i][j] represents whether s3[0…i+j-1] is an interleaving of s1[0…i-1] and s2[0…j-1].
- dp[0][0] = true, because an empty s1 and s2 can form an empty s3.
- Fill the First Row and First Column
- If s1 is empty, we can only form s3 by taking characters from s2.
- If s2 is empty, we can only form s3 by taking characters from s1.
- The DP formula checks whether s3[k] (where k = i + j) matches either:
- The current character of s1 (s1[i-1]), while ensuring that the previous part dp[i-1][j] is true.
- The current character of s2 (s2[j-1]), while ensuring that the previous part dp[i][j-1] is true.
- The DP table is filled iteratively until dp[m][n] contains the answer.
// C++ program to check if Check if a String is Interleaving
// of Other Two using Dynamic Programming
#include <bits/stdc++.h>
using namespace std;
// The main function that
// returns true if s3 is
// an interleaving of s1
// and s2, otherwise false.
bool isInterleave(string &s1, string &s2, string &s3)
{
int m = s1.size(), n = s2.size();
// s3 can be an interleaving of s1 and s2 only if
// the sum of lengths of s1 & s2 is equal to the length of s3.
if (m + n != s3.size())
return false;
vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
// Handle the corner case where both s1 and s2 are empty
dp[0][0] = true;
// Fill the first row (when s1 is empty)
for (int j = 1; j <= n; ++j)
{
dp[0][j] = (s2[j - 1] == s3[j - 1]) && dp[0][j - 1];
}
// Fill the first column (when s2 is empty)
for (int i = 1; i <= m; ++i)
{
dp[i][0] = (s1[i - 1] == s3[i - 1]) && dp[i - 1][0];
}
// Process all characters of s1 and s2
for (int i = 1; i <= m; ++i)
{
for (int j = 1; j <= n; ++j)
{
int k = i + j;
dp[i][j] = (s1[i - 1] == s3[k - 1] && dp[i - 1][j]) || (s2[j - 1] == s3[k - 1] && dp[i][j - 1]);
}
}
return dp[m][n];
}
int main()
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
cout << (isInterleave(s1, s2, s3) ? "true" : "false") << endl;
return 0;
}
// Java program to check if a String is Interleaving
// of Other Two using Dynamic Programming
import java.util.Arrays;
class GfG {
// The main function that
// returns true if s3 is
// an interleaving of s1
// and s2, otherwise false.
static boolean isInterleave(String s1, String s2,
String s3)
{
int m = s1.length();
int n = s2.length();
// s3 can be an interleaving of s1 and s2 only if
// the sum of lengths of s1 & s2 is equal to the
// length of s3.
if (m + n != s3.length())
return false;
boolean[][] dp = new boolean[m + 1][n + 1];
// Handle the corner case where both s1 and s2 are
// empty
dp[0][0] = true;
// Fill the first row (when 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 the first column (when 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];
}
// Process all characters of s1 and s2
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
int k = i + j;
dp[i][j]
= (s1.charAt(i - 1) == s3.charAt(k - 1)
&& dp[i - 1][j])
|| (s2.charAt(j - 1)
== s3.charAt(k - 1)
&& dp[i][j - 1]);
}
}
return dp[m][n];
}
public static void main(String[] args)
{
String s1 = "AAB";
String s2 = "AAC";
String s3 = "AAAABC";
System.out.println(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
# Python program to check if a String is Interleaving
# of Other Two using Dynamic Programming
def isInterleave(s1, s2, s3):
# The main function that
# returns true if s3 is
# an interleaving of s1
# and s2, otherwise false.
m = len(s1)
n = len(s2)
# s3 can be an interleaving of s1 and s2 only if
# the sum of lengths of s1 & s2 is equal to the length of s3.
if m + n != len(s3):
return False
dp = [[False] * (n + 1) for _ in range(m + 1)]
# Handle the corner case where both s1 and s2 are empty
dp[0][0] = True
# Fill the first row (when 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 the first column (when s2 is empty)
for i in range(1, m + 1):
dp[i][0] = (s1[i - 1] == s3[i - 1]) and dp[i - 1][0]
# Process all characters of s1 and s2
for i in range(1, m + 1):
for j in range(1, n + 1):
k = i + j
dp[i][j] = (s1[i - 1] == s3[k - 1] and dp[i - 1][j]) or \
(s2[j - 1] == s3[k - 1] 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# program to check if a String is Interleaving
// of Other Two using Dynamic Programming
using System;
class GfG {
// The main function that
// returns true if s3 is
// an interleaving of s1
// and s2, otherwise false.
static bool isInterleave(string s1, string s2,
string s3)
{
int m = s1.Length;
int n = s2.Length;
// s3 can be an interleaving of s1 and s2 only if
// the sum of lengths of s1 & s2 is equal to the
// length of s3.
if (m + n != s3.Length)
return false;
bool[, ] dp = new bool[m + 1, n + 1];
// Handle the corner case where both s1 and s2 are
// empty
dp[0, 0] = true;
// Fill the first row (when s1 is empty)
for (int j = 1; j <= n; ++j) {
dp[0, j]
= (s2[j - 1] == s3[j - 1]) && dp[0, j - 1];
}
// Fill the first column (when s2 is empty)
for (int i = 1; i <= m; ++i) {
dp[i, 0]
= (s1[i - 1] == s3[i - 1]) && dp[i - 1, 0];
}
// Process all characters of s1 and s2
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
int k = i + j;
dp[i, j] = (s1[i - 1] == s3[k - 1]
&& dp[i - 1, j])
|| (s2[j - 1] == s3[k - 1]
&& dp[i, j - 1]);
}
}
return dp[m, n];
}
static void Main(string[] args)
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
Console.WriteLine(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
// JavaScript program to check if a String is Interleaving
// of Other Two using Dynamic Programming
function isInterleave(s1, s2, s3)
{
// The main function that
// returns true if s3 is
// an interleaving of s1
// and s2, otherwise false.
let m = s1.length;
let n = s2.length;
// s3 can be an interleaving of s1 and s2 only if
// the sum of lengths of s1 & s2 is equal to the length
// of s3.
if (m + n !== s3.length)
return false;
let dp = Array(m + 1).fill(null).map(
() => Array(n + 1).fill(false));
// Handle the corner case where both s1 and s2 are empty
dp[0][0] = true;
// Fill the first row (when s1 is empty)
for (let j = 1; j <= n; ++j) {
dp[0][j]
= (s2[j - 1] === s3[j - 1]) && dp[0][j - 1];
}
// Fill the first column (when s2 is empty)
for (let i = 1; i <= m; ++i) {
dp[i][0]
= (s1[i - 1] === s3[i - 1]) && dp[i - 1][0];
}
// Process all characters of s1 and s2
for (let i = 1; i <= m; ++i) {
for (let j = 1; j <= n; ++j) {
let k = i + j;
dp[i][j]
= (s1[i - 1] === s3[k - 1] && dp[i - 1][j])
|| (s2[j - 1] === s3[k - 1]
&& dp[i][j - 1]);
}
}
return dp[m][n];
}
// Driver Code
let s1 = "AAB";
let s2 = "AAC";
let s3 = "AAAABC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");
Output
true
[Expected Approach] Space-Optimized DP – O(n * m) Time and O(m) Space
The idea is to optimize DP space by using two 1D arrays instead of a 2D table.
We check if s3 can be formed by interleaving s1 and s2 while maintaining relative order. prev stores results of the previous row, while cur stores the current row values.
We fill the first row for cases where s1 is empty, then iterate through both strings, updating cur[j] based on matches with s3. After processing a row, prev is updated with cur, ensuring space efficiency.
Steps to implement the above idea:
- Check if the total length matches, return false if not.
- Initialize two arrays prev and cur to store previous and current results.
- Set the base case where an empty prefix is valid.
- Fill the first row based on matches with s2.
- Iterate through both s1 and s2, updating cur based on matches.
- Return cur[m], indicating interleaving validity.














// CPP program to check if a string is
// interleaving of other two strings
#include <bits/stdc++.h>
using namespace std;
bool isInterleave(string &s1, string &s2, string &s3)
{
// return false is length of s3 is
// not equal to sum of lengths of s1 and s2
if (s1.size() + s2.size() != s3.size())
return false;
int n = s1.size(), m = s2.size();
// Create two arrays prev and cur to store
// results of previous and current states
vector<int> prev(m + 1), cur(m + 1);
// set empty strings as true
prev[0] = true;
// Fill the first row (when s1 is empty)
for (int j = 1; j <= m; ++j)
{
prev[j] = (s2[j - 1] == s3[j - 1]) && prev[j - 1];
}
// Process all characters of s1 and s2
for (int i = 1; i <= n; ++i)
{
// fill the first column of current row
cur[0] = (s1[i - 1] == s3[i - 1]) && prev[0];
for (int j = 1; j <= m; ++j)
{
int k = i + j;
cur[j] = (s1[i - 1] == s3[k - 1] && prev[j]) || (s2[j - 1] == s3[k - 1] && cur[j - 1]);
}
// store current row in previous row
prev = cur;
}
return cur[m];
}
int main()
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
cout << (isInterleave(s1, s2, s3) ? "true" : "false");
return 0;
}
// Java program to check if a string is
// interleaving of other two strings
import java.util.*;
class GfG {
static boolean isInterleave(String s1, String s2,
String s3)
{
// return false if length of s3 is
// not equal to sum of lengths of s1 and s2
if (s1.length() + s2.length() != s3.length())
return false;
int n = s1.length(), m = s2.length();
// Create two arrays prev and cur to store
// results of previous and current states
int[] prev = new int[m + 1];
int[] cur = new int[m + 1];
// set empty strings as true
prev[0] = 1;
// Fill the first row (when s1 is empty)
for (int j = 1; j <= m; ++j) {
prev[j] = (s2.charAt(j - 1) == s3.charAt(j - 1))
&& (prev[j - 1] == 1)
? 1
: 0;
}
// Process all characters of s1 and s2
for (int i = 1; i <= n; ++i) {
// fill the first column of current row
cur[0] = (s1.charAt(i - 1) == s3.charAt(i - 1))
&& (prev[0] == 1)
? 1
: 0;
for (int j = 1; j <= m; ++j) {
int k = i + j;
cur[j]
= ((s1.charAt(i - 1) == s3.charAt(k - 1)
&& prev[j] == 1)
|| (s2.charAt(j - 1)
== s3.charAt(k - 1)
&& cur[j - 1] == 1))
? 1
: 0;
}
// store current row in previous row
prev = Arrays.copyOf(cur, m + 1);
}
return cur[m] == 1;
}
public static void main(String[] args)
{
String s1 = "AAB";
String s2 = "AAC";
String s3 = "AAAABC";
System.out.println(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
# Python program to check if a string is
# interleaving of other two strings
def isInterleave(s1, s2, s3):
# return false if length of s3 is
# not equal to sum of lengths of s1 and s2
if len(s1) + len(s2) != len(s3):
return False
n, m = len(s1), len(s2)
# Create two arrays prev and cur to store
# results of previous and current states
prev = [0] * (m + 1)
cur = [0] * (m + 1)
# set empty strings as true
prev[0] = 1
# Fill the first row (when s1 is empty)
for j in range(1, m + 1):
prev[j] = int(s2[j - 1] == s3[j - 1] and prev[j - 1])
# Process all characters of s1 and s2
for i in range(1, n + 1):
# fill the first column of current row
cur[0] = int(s1[i - 1] == s3[i - 1] and prev[0])
for j in range(1, m + 1):
k = i + j
cur[j] = int((s1[i - 1] == s3[k - 1] and prev[j]) or
(s2[j - 1] == s3[k - 1] and cur[j - 1]))
# store current row in previous row
prev = cur[:]
return cur[m] == 1
if __name__ == "__main__":
s1 = "AAB"
s2 = "AAC"
s3 = "AAAABC"
print("true" if isInterleave(s1, s2, s3) else "false")
// C# program to check if a string is
// interleaving of other two strings
using System;
class GfG {
static bool isInterleave(string s1, string s2,
string s3)
{
// return false if length of s3 is
// not equal to sum of lengths of s1 and s2
if (s1.Length + s2.Length != s3.Length)
return false;
int n = s1.Length, m = s2.Length;
// Create two arrays prev and cur to store
// results of previous and current states
int[] prev = new int[m + 1];
int[] cur = new int[m + 1];
// set empty strings as true
prev[0] = 1;
// Fill the first row (when s1 is empty)
for (int j = 1; j <= m; ++j) {
prev[j] = (s2[j - 1] == s3[j - 1]
&& prev[j - 1] == 1)
? 1
: 0;
}
// Process all characters of s1 and s2
for (int i = 1; i <= n; ++i) {
// fill the first column of current row
cur[0]
= (s1[i - 1] == s3[i - 1] && prev[0] == 1)
? 1
: 0;
for (int j = 1; j <= m; ++j) {
int k = i + j;
cur[j] = ((s1[i - 1] == s3[k - 1]
&& prev[j] == 1)
|| (s2[j - 1] == s3[k - 1]
&& cur[j - 1] == 1))
? 1
: 0;
}
// store current row in previous row
Array.Copy(cur, prev, m + 1);
}
return cur[m] == 1;
}
static void Main()
{
string s1 = "AAB";
string s2 = "AAC";
string s3 = "AAAABC";
Console.WriteLine(
isInterleave(s1, s2, s3) ? "true" : "false");
}
}
// JavaScript program to check if a string is
// interleaving of other two strings
function isInterleave(s1, s2, s3)
{
// return false if length of s3 is
// not equal to sum of lengths of s1 and s2
if (s1.length + s2.length !== s3.length)
return false;
const n = s1.length, m = s2.length;
// Create two arrays prev and cur to store
// results of previous and current states
const prev = Array(m + 1).fill(0);
const cur = Array(m + 1).fill(0);
// set empty strings as true
prev[0] = 1;
// Fill the first row (when s1 is empty)
for (let j = 1; j <= m; ++j) {
prev[j] = (s2[j - 1] === s3[j - 1] && prev[j - 1])
? 1
: 0;
}
// Process all characters of s1 and s2
for (let i = 1; i <= n; ++i) {
// fill the first column of current row
cur[0]
= (s1[i - 1] === s3[i - 1] && prev[0]) ? 1 : 0;
for (let j = 1; j <= m; ++j) {
const k = i + j;
cur[j] = ((s1[i - 1] === s3[k - 1] && prev[j])
|| (s2[j - 1] === s3[k - 1]
&& cur[j - 1]))
? 1
: 0;
}
// store current row in previous row
prev.splice(0, m + 1, ...cur);
}
return !!cur[m];
}
// Driver Code
const s1 = "AAB";
const s2 = "AAC";
const s3 = "AAAABC";
console.log(isInterleave(s1, s2, s3) ? "true" : "false");
Output
true