Check if a string is a scrambled form of another string - GeeksforGeeks

16 Dec, 2021
Given two strings S1 and S2 of equal length, the task is to determine if S2 is a scrambled form of S1.Scrambled string: Given string str, we can represent it as a binary tree by partitioning it into two non-empty substrings recursively.Note: Scrambled string is not same as an AnagramBelow is one possible representation of str = “coder”: 
    coder
   /    \
  co    der
 / \    /  \
c   o  d   er
           / \
          e   r
To scramble the string, we may choose any non-leaf node and swap its two children. Suppose, we choose the node “co” and swap its two children, it produces a scrambled string “ocder”. 
    ocder
   /    \
  oc    der
 / \    /  \
o   c  d   er
           / \
          e   r
Thus, “ocder” is a scrambled string of “coder”.Similarly, if we continue to swap the children of nodes “der” and “er”, it produces a scrambled string “ocred”. 
    ocred
   /    \
  oc    red
 / \    /  \
o   c  re  d
       / \
      r   e
Thus, “ocred” is a scrambled string of “coder”.Examples:
Input: S1=”coder”, S2=”ocder” Output: Yes Explanation: “ocder” is a scrambled form of “coder”Input: S1=”abcde”, S2=”caebd” Output: No Explanation: “caebd” is not a scrambled form of “abcde”
Approach In order to solve this problem, we are using Divide and Conquer approach. Given two strings of equal length (say n+1), S1[0...n] and S2[0...n]. If S2 is a scrambled form of S1, then there must exist an index i such that at least one of the following conditions is true:  
S2[0...i] is a scrambled string of S1[0...i] and S2[i+1...n] is a scrambled string of S1[i+1...n].
S2[0...i] is a scrambled string of S1[n-i...n] and S2[i+1...n] is a scrambled string of S1[0...n-i-1].
Note: An optimization step to consider here is to check beforehand if the two strings are anagrams of each other. If not, it indicates that the strings contain different characters and can’t be a scrambled form of each other.Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ Program to check if a// given string is a scrambled// form of another string #include <bits/stdc++.h>using namespace std; bool isScramble(string S1, string S2){    // Strings of non-equal length    // cant' be scramble strings    if (S1.length() != S2.length()) {        return false;    }     int n = S1.length();     // Empty strings are scramble strings    if (n == 0) {        return true;    }     // Equal strings are scramble strings    if (S1 == S2) {        return true;    }     // Check for the condition of anagram    string copy_S1 = S1, copy_S2 = S2;     sort(copy_S1.begin(), copy_S1.end());    sort(copy_S2.begin(), copy_S2.end());     if (copy_S1 != copy_S2) {        return false;    }     for (int i = 1; i < n; i++) {         // Check if S2[0...i] is a scrambled        // string of S1[0...i] and if S2[i+1...n]        // is a scrambled string of S1[i+1...n]        if (isScramble(S1.substr(0, i), S2.substr(0, i))            && isScramble(S1.substr(i, n - i),                          S2.substr(i, n - i))) {            return true;        }         // Check if S2[0...i] is a scrambled        // string of S1[n-i...n] and S2[i+1...n]        // is a scramble string of S1[0...n-i-1]        if (isScramble(S1.substr(0, i),                       S2.substr(n - i, i))            && isScramble(S1.substr(i, n - i),                          S2.substr(0, n - i))) {            return true;        }    }     // If none of the above    // conditions are satisfied    return false;} // Driver Codeint main(){    string S1 = "coder";    string S2 = "ocred";     if (isScramble(S1, S2)) {        cout << "Yes";    }    else {        cout << "No";    }     return 0;}
// Java program to check if a// given string is a scrambled// form of another stringimport java.util.*; class GFG{     static boolean isScramble(String S1,                          String S2){         // Strings of non-equal length    // cant' be scramble strings    if (S1.length() != S2.length())    {        return false;    }         int n = S1.length();     // Empty strings are scramble strings    if (n == 0)    {        return true;    }         // Equal strings are scramble strings    if (S1.equals(S2))    {        return true;    }         // Converting string to    // character array    char[] tempArray1 = S1.toCharArray();    char[] tempArray2 = S2.toCharArray();         // Checking condition for Anagram    Arrays.sort(tempArray1);    Arrays.sort(tempArray2);         String copy_S1 = new String(tempArray1);    String copy_S2 = new String(tempArray2);         if (!copy_S1.equals(copy_S2))    {        return false;    }             for(int i = 1; i < n; i++)    {                 // Check if S2[0...i] is a scrambled        // string of S1[0...i] and if S2[i+1...n]        // is a scrambled string of S1[i+1...n]        if (isScramble(S1.substring(0, i),                       S2.substring(0, i)) &&            isScramble(S1.substring(i, n),                       S2.substring(i, n)))        {            return true;        }         // Check if S2[0...i] is a scrambled        // string of S1[n-i...n] and S2[i+1...n]        // is a scramble string of S1[0...n-i-1]        if (isScramble(S1.substring(n - i, n),                       S2.substring(0, i)) &&            isScramble(S1.substring(0, n - i),                       S2.substring(i, n)))        {            return true;        }    }         // If none of the above    // conditions are satisfied    return false;} // Driver Codepublic static void main(String[] args){    String S1 = "coder";    String S2 = "ocred";         if (isScramble(S1, S2))    {        System.out.println("Yes");    }    else    {        System.out.println("No");    }}} // This code is contributed by dadi madhav
# Python3 program to check if a# given string is a scrambled# form of another stringdef isScramble(S1: str, S2: str):         # Strings of non-equal length    # cant' be scramble strings    if len(S1) != len(S2):        return False     n = len(S1)     # Empty strings are scramble strings    if not n:        return True     # Equal strings are scramble strings    if S1 == S2:        return True     # Check for the condition of anagram    if sorted(S1) != sorted(S2):        return False     for i in range(1, n):                 # Check if S2[0...i] is a scrambled        # string of S1[0...i] and if S2[i+1...n]        # is a scrambled string of S1[i+1...n]        if (isScramble(S1[:i], S2[:i]) and            isScramble(S1[i:], S2[i:])):            return True         # Check if S2[0...i] is a scrambled        # string of S1[n-i...n] and S2[i+1...n]        # is a scramble string of S1[0...n-i-1]        if (isScramble(S1[-i:], S2[:i]) and            isScramble(S1[:-i], S2[i:])):            return True     # If none of the above    # conditions are satisfied    return False # Driver Codeif __name__ == "__main__":         S1 = "coder"    S2 = "ocred"         if (isScramble(S1, S2)):        print("Yes")    else:        print("No") # This code is contributed by sgshah2
// C# program to check if a// given string is a scrambled// form of another stringusing System;using System.Collections.Generic;class GFG {         static bool isScramble(string S1, string S2)    {                   // Strings of non-equal length        // cant' be scramble strings        if (S1.Length != S2.Length)         {            return false;        }                   int n = S1.Length;               // Empty strings are scramble strings        if (n == 0)         {            return true;        }                   // Equal strings are scramble strings        if (S1.Equals(S2))        {            return true;        }                   // Converting string to         // character array        char[] tempArray1 = S1.ToCharArray();        char[] tempArray2 = S2.ToCharArray();                   // Checking condition for Anagram        Array.Sort(tempArray1);        Array.Sort(tempArray2);                   string copy_S1 = new string(tempArray1);        string copy_S2 = new string(tempArray2);                   if (!copy_S1.Equals(copy_S2))         {            return false;        }                       for(int i = 1; i < n; i++)        {                           // Check if S2[0...i] is a scrambled            // string of S1[0...i] and if S2[i+1...n]            // is a scrambled string of S1[i+1...n]            if (isScramble(S1.Substring(0, i),                            S2.Substring(0, i)) &&                 isScramble(S1.Substring(i, n - i),                           S2.Substring(i, n - i)))            {                return true;            }                   // Check if S2[0...i] is a scrambled            // string of S1[n-i...n] and S2[i+1...n]            // is a scramble string of S1[0...n-i-1]            if (isScramble(S1.Substring(0, i),                           S2.Substring(n - i, i)) &&                 isScramble(S1.Substring(i, n - i),                           S2.Substring(0, n - i)))             {                return true;            }        }                   // If none of the above        // conditions are satisfied        return false;    }     // Driver code  static void Main()  {        string S1 = "coder";        string S2 = "ocred";                   if (isScramble(S1, S2))         {            Console.WriteLine("Yes");        }        else        {            Console.WriteLine("No");        }  }} // This code is contributed by divyeshrabadiya07
<script>    // Javascript program to check if a    // given string is a scrambled    // form of another string         function isScramble(S1, S2)    {         // Strings of non-equal length        // can't be scramble strings        if (S1.length != S2.length)        {            return false;        }         let n = S1.length;         // Empty strings are scramble strings        if (n == 0)        {            return true;        }         // Equal strings are scramble strings        if (S1 == S2)        {            return true;        }         // Converting string to        // character array        let tempArray1 = S1.split('');        let tempArray2 = S2.split('');         // Checking condition for Anagram        tempArray1.sort();        tempArray2.sort();         let copy_S1 = tempArray1.join("");        let copy_S2 = tempArray2.join("");         if (copy_S1 != copy_S2)        {            return false;        }         for(let i = 1; i < n; i++)        {             // Check if S2[0...i] is a scrambled            // string of S1[0...i] and if S2[i+1...n]            // is a scrambled string of S1[i+1...n]            if (isScramble(S1.substring(0, i),                           S2.substring(0, i)) &&                isScramble(S1.substring(i, i + n),                           S2.substring(i, i + n)))            {                return true;            }             // Check if S2[0...i] is a scrambled            // string of S1[n-i...n] and S2[i+1...n]            // is a scramble string of S1[0...n-i-1]            if (isScramble(S1.substring(n - i, n - i + n),                           S2.substring(0, i)) &&                isScramble(S1.substring(0, n - i),                           S2.substring(i, i + n)))            {                return true;            }        }         // If none of the above        // conditions are satisfied        return false;    }         let S1 = "coder";    let S2 = "ocred";          if (isScramble(S1, S2))    {        document.write("Yes");    }    else    {        document.write("No");    } // This code is contributed by decode2207.</script>
Yes
Time Complexity: O(2^k + 2^(n-k)), where k and n-k are the length of the two substrings.
Auxiliary Space: O(2^N), recursion stack.
Dynamic Programming Solution: The above recursive Code can be optimized by storing Boolean values of substrings in an unordered map, so if the same substrings have to be checked again we can easily just get value from the map instead of performing function calls.
Memoized Code: 
C++
Java
Python3
C#
Javascript
// C++ Program to check if a// given string is a scrambled// form of another string #include <bits/stdc++.h>using namespace std; // map declaration for storing key value pair// means for storing subproblem resultunordered_map<string, bool> mp; bool isScramble(string S1, string S2){    // Strings of non-equal length    // cant' be scramble strings    if (S1.length() != S2.length()) {        return false;    }     int n = S1.length();     // Empty strings are scramble strings    if (n == 0) {        return true;    }     // Equal strings are scramble strings    if (S1 == S2) {        return true;    }    // Check for the condition of anagram    string copy_S1 = S1, copy_S2 = S2;     sort(copy_S1.begin(), copy_S1.end());    sort(copy_S2.begin(), copy_S2.end());     if (copy_S1 != copy_S2) {        return false;    }     // make key of type string for search in map    string key = (S1 + " " + S2);    // checking if both string are before calculated or not    // if calculated means find in map then return it's    // value    if (mp.find(key) != mp.end()) {        return mp[key];    }     // declaring flag variable to store result    bool flag = false;     for (int i = 1; i < n; i++) {         // Check if S2[0...i] is a scrambled        // string of S1[0...i] and if S2[i+1...n]        // is a scrambled string of S1[i+1...n]        if (isScramble(S1.substr(0, i), S2.substr(0, i))            && isScramble(S1.substr(i, n - i),                          S2.substr(i, n - i))) {            flag = true;            return true;        }         // Check if S2[0...i] is a scrambled        // string of S1[n-i...n] and S2[i+1...n]        // is a scramble string of S1[0...n-i-1]        if (isScramble(S1.substr(0, i), S2.substr(n - i, i))            && isScramble(S1.substr(i, n - i),                          S2.substr(0, n - i))) {            flag = true;            return true;        }    }     // add key & flag value to map (store for future use)    // so next time no required to calculate it again    mp[key] = flag;     // If none of the above conditions are satisfied    return false;} // Driver Codeint main(){    string S1 = "coder";    string S2 = "ocred";     if (isScramble(S1, S2)) {        cout << "Yes";    }    else {        cout << "No";    }     return 0;}
// Java Program to check if a// given string is a scrambled// form of another stringimport java.util.*;public class Main{    // map declaration for storing key value pair    // means for storing subproblem result    static HashMap<String, Boolean> mp = new HashMap<String, Boolean>();       static boolean isScramble(String S1, String S2)    {                // Strings of non-equal length        // cant' be scramble strings        if (S1.length() != S2.length()) {            return false;        }           int n = S1.length();           // Empty strings are scramble strings        if (n != 0) {            return true;        }           // Equal strings are scramble strings        if (S1 == S2) {            return true;        }        // Check for the condition of anagram        String copy_S1 = S1, copy_S2 = S2;        char[] t1 = copy_S1.toCharArray();        char[] t2 = copy_S2.toCharArray();        Arrays.sort(t1);        Arrays.sort(t2);        copy_S1 = new String(t1);        copy_S2 = new String(t2);           if (!copy_S1.equals(copy_S2)) {            return false;        }           // make key of type string for search in map        String key = (S1 + " " + S2);        // checking if both string are before calculated or not        // if calculated means find in map then return it's        // value        if (mp.containsKey(key)) {            return mp.get(key);        }           // declaring flag variable to store result        boolean flag = false;           for (int i = 1; i < n; i++) {               // Check if S2[0...i] is a scrambled            // string of S1[0...i] and if S2[i+1...n]            // is a scrambled string of S1[i+1...n]            if (isScramble(S1.substring(0, i), S2.substring(0, i))                && isScramble(S1.substring(i, n), S2.substring(i, n))) {                flag = true;                return true;            }               // Check if S2[0...i] is a scrambled            // string of S1[n-i...n] and S2[i+1...n]            // is a scramble string of S1[0...n-i-1]            if (isScramble(S1.substring(0, i), S2.substring(n - i, n))                && isScramble(S1.substring(i, n),                              S2.substring(0, n - i))) {                flag = true;                return true;            }        }           // add key & flag value to map (store for future use)        // so next time no required to calculate it again        mp.put(key, flag);           // If none of the above conditions are satisfied        return false;    }         public static void main(String[] args) {        String S1 = "coder";        String S2 = "ocred";                if (isScramble(S1, S2)) {            System.out.print("Yes");        }        else {            System.out.print("No");        }    }} // This code is contributed by divyesh072019.
# Declaring unordered map globallymap={}# Python3 program to check if a# given string is a scrambled# form of another stringdef isScramble(S1: str, S2: str):         # Strings of non-equal length    # cant' be scramble strings    if len(S1) != len(S2):        return False     n = len(S1)     # Empty strings are scramble strings    if not n:        return True     # Equal strings are scramble strings    if S1 == S2:        return True     # Check for the condition of anagram    if sorted(S1) != sorted(S2):        return False         # Checking if both Substrings are in    # map or are already calculated or not    if(S1+' '+S2 in map):        return map[S1+' '+S2]         # Declaring a flag variable    flag = False     for i in range(1, n):                 # Check if S2[0...i] is a scrambled        # string of S1[0...i] and if S2[i+1...n]        # is a scrambled string of S1[i+1...n]        if (isScramble(S1[:i], S2[:i]) and            isScramble(S1[i:], S2[i:])):            flag = True            return True         # Check if S2[0...i] is a scrambled        # string of S1[n-i...n] and S2[i+1...n]        # is a scramble string of S1[0...n-i-1]        if (isScramble(S1[-i:], S2[:i]) and            isScramble(S1[:-i], S2[i:])):            flag = True            return True         # Storing calculated value to map    map[S1+" "+S2] = flag         # If none of the above    # conditions are satisfied    return False # Driver Codeif __name__ == "__main__":         S1 = "great"    S2 = "rgate"         if (isScramble(S1, S2)):        print("Yes")    else:        print("No")
// C# Program to check if a// given string is a scrambled// form of another stringusing System;using System.Collections.Generic;class GFG {         // map declaration for storing key value pair    // means for storing subproblem result    static Dictionary<string, bool> mp = new Dictionary<string, bool>();      static bool isScramble(string S1, string S2)    {               // Strings of non-equal length        // cant' be scramble strings        if (S1.Length != S2.Length) {            return false;        }          int n = S1.Length;          // Empty strings are scramble strings        if (n == 0) {            return true;        }          // Equal strings are scramble strings        if (S1 == S2) {            return true;        }        // Check for the condition of anagram        string copy_S1 = S1, copy_S2 = S2;        char[] t1 = copy_S1.ToCharArray();        char[] t2 = copy_S2.ToCharArray();        Array.Sort(t1);        Array.Sort(t2);        copy_S1 = new string(t1);        copy_S2 = new string(t2);          if (copy_S1 != copy_S2) {            return false;        }          // make key of type string for search in map        string key = (S1 + " " + S2);        // checking if both string are before calculated or not        // if calculated means find in map then return it's        // value        if (mp.ContainsKey(key)) {            return mp[key];        }          // declaring flag variable to store result        bool flag = false;          for (int i = 1; i < n; i++) {              // Check if S2[0...i] is a scrambled            // string of S1[0...i] and if S2[i+1...n]            // is a scrambled string of S1[i+1...n]            if (isScramble(S1.Substring(0, i), S2.Substring(0, i))                && isScramble(S1.Substring(i, n - i), S2.Substring(i, n - i))) {                flag = true;                return true;            }              // Check if S2[0...i] is a scrambled            // string of S1[n-i...n] and S2[i+1...n]            // is a scramble string of S1[0...n-i-1]            if (isScramble(S1.Substring(0, i), S2.Substring(n - i, i))                && isScramble(S1.Substring(i, n - i),                              S2.Substring(0, n - i))) {                flag = true;                return true;            }        }          // add key & flag value to map (store for future use)        // so next time no required to calculate it again        mp[key] = flag;          // If none of the above conditions are satisfied        return false;    }       static void Main() {    string S1 = "coder";    string S2 = "ocred";       if (isScramble(S1, S2)) {        Console.Write("Yes");    }    else {        Console.Write("No");    }  }} // This code is contributed by rameshtravel07.
<script>    // Javascript Program to check if a    // given string is a scrambled    // form of another string         // map declaration for storing key value pair    // means for storing subproblem result    let mp = new Map();     function isScramble(S1, S2)    {        // Strings of non-equal length        // cant' be scramble strings        if (S1.length != S2.length) {            return false;        }         let n = S1.length;         // Empty strings are scramble strings        if (n == 0) {            return true;        }         // Equal strings are scramble strings        if (S1 == S2) {            return true;        }        // Check for the condition of anagram        let copy_S1 = S1, copy_S2 = S2;        let t1 = copy_S1.split('')        let t2 = copy_S2.split('')        t1.sort();        t2.sort();        copy_S1 = t1.join("");        copy_S2 = t2.join("");         if (copy_S1 != copy_S2) {            return false;        }         // make key of type string for search in map        let key = (S1 + " " + S2);        // checking if both string are before calculated or not        // if calculated means find in map then return it's        // value        if (mp.has(key)) {            return mp[key];        }         // declaring flag variable to store result        let flag = false;         for (let i = 1; i < n; i++) {             // Check if S2[0...i] is a scrambled            // string of S1[0...i] and if S2[i+1...n]            // is a scrambled string of S1[i+1...n]            if (isScramble(S1.substring(0, i), S2.substring(0, i))                && isScramble(S1.substring(i, n),                              S2.substring(i, n))) {                flag = true;                return true;            }             // Check if S2[0...i] is a scrambled            // string of S1[n-i...n] and S2[i+1...n]            // is a scramble string of S1[0...n-i-1]            if (isScramble(S1.substring(0, i), S2.substring(n - i, n))                && isScramble(S1.substring(i, n),                              S2.substring(0, n - i))) {                flag = true;                return true;            }        }         // add key & flag value to map (store for future use)        // so next time no required to calculate it again        mp[key] = flag;         // If none of the above conditions are satisfied        return false;    }         let S1 = "coder";    let S2 = "ocred";      if (isScramble(S1, S2)) {        document.write("Yes");    }    else {        document.write("No");    } // This code is contributed by suresh07.</script>
Yes
Time Complexity: O(N^2), where N is the length of the given strings.Auxiliary Space: O(N^2), As we need to store O(N^2) string in our mp map.
amarjeet_singh
sgshah2
dadimadhav
divyeshrabadiya07
decode2207
taran910
ajaymakvana
bunnyram19
pankajsharmagfg
suresh07
rameshtravel07
divyesh072019
arpitdadhich045
Algorithms
Divide and Conquer
Recursion
Strings
Tree
Strings
Recursion
Divide and Conquer
Tree
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
SDE SHEET - A Complete Guide for SDE Preparation
DSA Sheet by Love Babbar
How to Start Learning DSA?
Understanding Time Complexity with Simple Examples
How to write a Pseudo Code?
Merge Sort
QuickSort
Binary Search
Maximum and minimum of an array using minimum number of comparisons
Program for Tower of Hanoi