Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Interview Problems on DP
  • Practice DP
  • MCQs on DP
  • Tutorial on Dynamic Programming
  • Optimal Substructure
  • Overlapping Subproblem
  • Memoization
  • Tabulation
  • Tabulation vs Memoization
  • 0/1 Knapsack
  • Unbounded Knapsack
  • Subset Sum
  • LCS
  • LIS
  • Coin Change
  • Word Break
  • Egg Dropping Puzzle
  • Matrix Chain Multiplication
  • Palindrome Partitioning
  • DP on Arrays
  • DP with Bitmasking
  • Digit DP
  • DP on Trees
  • DP on Graph
Open In App
Next Article:
Check if two strings are permutation of each other
Next article icon

Check if a String is Interleaving of Other Two

Last Updated : 25 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report
Try it on GfG Practice
redirect icon

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 = "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
  • [Better Approach 1] Using Top-Down DP - O(m*n) Time and O(n*m) Space
  • [Better Approach 2] Using Bottom-Up DP - O(m*n) Time and O(m*n) Space
  • [Expected Approach] Space-Optimized DP - O(n * m) Time and O(m) Space

[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.
C++
// 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
// 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
# 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#
// 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
// 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++
// 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
// 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
# 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#
// 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
// 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++
// 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
// 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
# 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#
// 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
// 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.


C++
// 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
// 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
# 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#
// 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
// 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

Next Article
Check if two strings are permutation of each other
author
kartik
Improve
Article Tags :
  • Strings
  • Dynamic Programming
  • DSA
  • Microsoft
  • Yahoo
  • Google
  • FactSet
  • Zillious
Practice Tags :
  • FactSet
  • Google
  • Microsoft
  • Yahoo
  • Zillious
  • Dynamic Programming
  • Strings

Similar Reads

  • Print all interleavings of given two strings
    Given two strings str1 and str2, write a function that prints all interleavings of the given two strings. You may assume that all characters in both strings are different Example: Input: str1 = "AB", str2 = "CD"Output: ABCD ACBD ACDB CABD CADB CDABInput: str1 = "AB", str2 = "C"Output: ABC ACB CAB An
    14 min read
  • Check if two Strings are Anagrams of each other
    Given two strings s1 and s2 consisting of lowercase characters, the task is to check whether the two given strings are anagrams of each other or not. An anagram of a string is another string that contains the same characters, only the order of characters can be different. Examples: Input: s1 = “geek
    13 min read
  • Check if two strings are same or not
    Given two strings, the task is to check if these two strings are identical(same) or not. Consider case sensitivity. Examples: Input: s1 = "abc", s2 = "abc" Output: Yes Input: s1 = "", s2 = "" Output: Yes Input: s1 = "GeeksforGeeks", s2 = "Geeks" Output: No Approach - By Using (==) in C++/Python/C#,
    7 min read
  • Check if two strings are permutation of each other
    Write a function to check whether two given strings are Permutation of each other or not. A Permutation of a string is another string that contains same characters, only the order of characters can be different. For example, "abcd" and "dabc" are Permutation of each other. We strongly recommend that
    13 min read
  • Check if a string is Isogram or not
    Given a word or phrase, check if it is an isogram or not. An Isogram is a word in which no letter occurs more than once Examples: Input: MachineOutput: TrueExplanation: "Machine" does not have any character repeating, it is an Isogram Input : GeekOutput : FalseExplanation: "Geek" has 'e' as repeatin
    9 min read
  • Interleaving of two given strings with no common characters
    Given three strings s1, s2 and s3. check whether s3 is an interleaving of s1 and s2. It may be assumed that there is no common character between s1 and s2 A string s3 is said to be interleaving s1 and s2, if it contains all characters of s1 and s2 and order of all characters in individual strings is
    10 min read
  • Check whether a given string is Heterogram or not
    Given a string S. The task is to check whether a the given string is Heterogram or not. A heterogram is a word, phrase, or sentence in which no letter of the alphabet occurs more than once. Examples: Input : S = "the big dwarf only jumps" Output : Yes Each alphabet in the string S is occurred only o
    4 min read
  • Check if one string is subsequence of other
    Given two strings s1 and s2, find if the first string is a Subsequence of the second string, i.e. if s1 is a subsequence of s2. A subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements. Examples : Input: s1 =
    10 min read
  • Check if the given string is IPv4 or IPv6 or Invalid
    Given a string S consisting of N characters, the task is to check if the given string S is IPv4 or IPv6 or Invalid. If the given string S is a valid IPv4, then print "IPv4", if the string S is a valid IPv6, then print "IPv4". Otherwise, print "-1". A valid IPv4 address is an IP in the form "x1.x2.x3
    14 min read
  • Check if two strings have a common substring
    You are given two strings str1 and str2. You have to check if the two strings share a common substring. Examples : Input : str1 = "HELLO" str2 = "WORLD" Output : YES Explanation : The substrings "O" and "L" are common to both str1 and str2 Input : str1 = "HI" str2 = "ALL" Output : NO Explanation : B
    5 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences