VOOZH about

URL: https://www.geeksforgeeks.org/dsa/find-if-a-string-is-interleaved-of-two-other-strings-dp-33/

⇱ Check if a String is Interleaving of Other Two - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Check if a String is Interleaving of Other Two

Last Updated : 8 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.

Output
true

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

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

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

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


Output
true

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

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

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

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

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


Output
true

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

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

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


Output
true
Comment