|
| 1 | +--- |
| 2 | +id: Scrambled-String |
| 3 | +title: Scrambled-String (Geeks for Geeks) |
| 4 | +sidebar_label: Scrambled-String |
| 5 | +tags: |
| 6 | + - Intermediate |
| 7 | + - Geeks for Geeks |
| 8 | + - CPP |
| 9 | + - Python |
| 10 | + - DSA |
| 11 | +description: "This is a solution to the Scrambled-String problem on Geeks for Geeks." |
| 12 | +--- |
| 13 | + |
| 14 | +## Problem Description |
| 15 | + |
| 16 | +Given two strings S1 and S2 of equal length, the task is to determine if S2 is a scrambled form of S1. |
| 17 | + |
| 18 | +Scrambled string: Given string str, we can represent it as a binary tree by partitioning it into two non-empty substrings recursively. |
| 19 | +Below is one possible representation of str = coder: |
| 20 | + |
| 21 | +To scramble the string, we may choose any non-leaf node and swap its two children. |
| 22 | +Suppose, we choose the node co and swap its two children, it produces a scrambled string ocder. |
| 23 | +Similarly, if we continue to swap the children of nodes der and er, it produces a scrambled string ocred. |
| 24 | + |
| 25 | +Note: Scrambled string is not the same as an Anagram. |
| 26 | +Print "Yes" if S2 is a scrambled form of S1 otherwise print "No". |
| 27 | + |
| 28 | + |
| 29 | +## Examples |
| 30 | + |
| 31 | +**Example:** |
| 32 | + |
| 33 | +Consider the following graph: |
| 34 | + |
| 35 | +``` |
| 36 | + ocder |
| 37 | + / \ |
| 38 | + oc der |
| 39 | + / \ |
| 40 | + o c |
| 41 | +``` |
| 42 | +**Input:** S1="coder", S2="ocder" |
| 43 | +**Explanation:** ocder is a scrambled |
| 44 | +form of coder. |
| 45 | +**Output:** Yes |
| 46 | + |
| 47 | +## Your Task |
| 48 | + |
| 49 | +You don't need to read input or print anything. You only need to complete the function isScramble() which takes two strings S1 and S2 as input and returns a boolean value. |
| 50 | + |
| 51 | +Expected Time Complexity: $O(N2)$. |
| 52 | +Expected Auxiliary Space: $O(N2)$. |
| 53 | + |
| 54 | +## Constraints |
| 55 | + |
| 56 | +- S1.length = S2.length |
| 57 | +- `S1.length<=31` |
| 58 | +- S1 and S2 consist of lower-case English letters. |
| 59 | + |
| 60 | +## Problem Explanation |
| 61 | + |
| 62 | +Here's the step-by-step breakdown of the Scrambled String process: |
| 63 | + |
| 64 | +**Step 1 :** A scrambled string is defined based on recursive partitioning and swapping of substrings. Here’s a more detailed explanation: |
| 65 | + |
| 66 | +**Step 2 :** Binary Tree Representation:Given a string str, you can represent it as a binary tree by recursively partitioning it into two non-empty substrings. |
| 67 | +**Step 3 :** For example, for the string "coder": You can split it into "co" and "der". |
| 68 | +Each of these can be further split recursively, forming a binary tree structure. |
| 69 | +**Step 4 :**Scrambling: A string S2 is a scrambled form of string S1 if S2 can be obtained by swapping the left and right children of some non-leaf nodes in the binary tree representation of S1. |
| 70 | +For instance, "coder" can be scrambled to "ocder" by swapping "co" and "der", then further scrambling "co" to "oc". |
| 71 | + |
| 72 | +### Code Implementation |
| 73 | + |
| 74 | +<Tabs> |
| 75 | + <TabItem value="Python" label="Python" default> |
| 76 | + <SolutionAuthor name="@ngmuraqrdd"/> |
| 77 | + ```python |
| 78 | +class Solution(object): |
| 79 | + def isScramble(self, s1, s2): |
| 80 | + """ |
| 81 | + :type s1: str |
| 82 | + :type s2: str |
| 83 | + :rtype: bool |
| 84 | + """ |
| 85 | + # Base cases |
| 86 | + |
| 87 | + n = len(s1) |
| 88 | + |
| 89 | + # If both strings are not equal in size |
| 90 | + if len(s2) != n: |
| 91 | + return False |
| 92 | + |
| 93 | + # If both strings are equal |
| 94 | + if s1 == s2: |
| 95 | + return True |
| 96 | + |
| 97 | + # If code is reached to this condition then following this are sure: |
| 98 | + # 1. size of both string is equal |
| 99 | + # 2. string are not equal |
| 100 | + # so size is equal (where size==1) and they are not equal then obviously false |
| 101 | + # example 'a' and 'b' size is equal, string are not equal |
| 102 | + if n == 1: |
| 103 | + return False |
| 104 | + |
| 105 | + key = s1 + " " + s2 |
| 106 | + |
| 107 | + # Check if this problem has already been solved |
| 108 | + if key in self.mp: |
| 109 | + return self.mp[key] |
| 110 | + |
| 111 | + # For every iteration it can two condition |
| 112 | + # 1. We should proceed without swapping |
| 113 | + # 2. We should swap before looking next |
| 114 | + for i in range(1, n): |
| 115 | + # ex of without swap: gr|eat and rg|eat |
| 116 | + without_swap = ( |
| 117 | + # Left part of first and second string |
| 118 | + self.isScramble(s1[:i], s2[:i]) |
| 119 | + and |
| 120 | + # Right part of first and second string; |
| 121 | + self.isScramble(s1[i:], s2[i:]) |
| 122 | + ) |
| 123 | + |
| 124 | + # If without swap gives us the right answer then we do not need |
| 125 | + # to call the recursion with swap |
| 126 | + if without_swap: |
| 127 | + return True |
| 128 | + |
| 129 | + # ex of with swap: gr|eat rge|at |
| 130 | + # here we compare "gr" with "at" and "eat" with "rge" |
| 131 | + with_swap = ( |
| 132 | + # Left part of first and right part of second |
| 133 | + self.isScramble(s1[:i], s2[n-i:]) |
| 134 | + and |
| 135 | + # Right part of first and left part of second |
| 136 | + self.isScramble(s1[i:], s2[:n-i]) |
| 137 | + ) |
| 138 | + |
| 139 | + # If with swap gives us the right answer then we return True |
| 140 | + # otherwise, the for loop does its work |
| 141 | + if with_swap: |
| 142 | + return True |
| 143 | + |
| 144 | + self.mp[key] = False |
| 145 | + return False |
| 146 | + |
| 147 | + # for storing already solved problems |
| 148 | + mp = {} |
| 149 | + ``` |
| 150 | + </TabItem> |
| 151 | + |
| 152 | + <TabItem value="C++" label="C++" default> |
| 153 | + <SolutionAuthor name="@ngmuraqrdd"/> |
| 154 | + ```cpp |
| 155 | +class Solution { |
| 156 | +public: |
| 157 | +//for storing already solved problems |
| 158 | + unordered_map<string,bool> mp; |
| 159 | + |
| 160 | + |
| 161 | + bool isScramble(string s1, string s2) { |
| 162 | + //base cases |
| 163 | + |
| 164 | + int n = s1.size(); |
| 165 | + |
| 166 | + //if both string are not equal in size |
| 167 | + if(s2.size()!=n) |
| 168 | + return false; |
| 169 | + |
| 170 | + //if both string are equal |
| 171 | + if(s1==s2) |
| 172 | + return true; |
| 173 | + |
| 174 | + |
| 175 | + |
| 176 | + //if code is reached to this condition then following this are sure: |
| 177 | + //1. size of both string is equal |
| 178 | + //2. string are not equal |
| 179 | + //so size is equal (where size==1) and they are not equal then obviously false |
| 180 | + //example 'a' and 'b' size is equal ,string are not equal |
| 181 | + if(n==1) |
| 182 | + return false; |
| 183 | + |
| 184 | + string key = s1+" "+s2; |
| 185 | + |
| 186 | + //check if this problem has already been solved |
| 187 | + if(mp.find(key)!=mp.end()) |
| 188 | + return mp[key]; |
| 189 | + |
| 190 | + //for every iteration it can two condition |
| 191 | + //1.we should proceed without swapping |
| 192 | + //2.we should swap before looking next |
| 193 | + for(int i=1;i<n;i++) |
| 194 | + { |
| 195 | + |
| 196 | + //ex of without swap: gr|eat and rg|eat |
| 197 | + bool withoutswap = ( |
| 198 | + //left part of first and second string |
| 199 | + isScramble(s1.substr(0,i),s2.substr(0,i)) |
| 200 | + |
| 201 | + && |
| 202 | + |
| 203 | + //right part of first and second string; |
| 204 | + isScramble(s1.substr(i),s2.substr(i)) |
| 205 | + ); |
| 206 | + |
| 207 | + |
| 208 | + |
| 209 | + //if without swap give us right answer then we do not need |
| 210 | + //to call the recursion withswap |
| 211 | + if(withoutswap) |
| 212 | + return true; |
| 213 | + |
| 214 | + //ex of withswap: gr|eat rge|at |
| 215 | + //here we compare "gr" with "at" and "eat" with "rge" |
| 216 | + bool withswap = ( |
| 217 | + //left part of first and right part of second |
| 218 | + isScramble(s1.substr(0,i),s2.substr(n-i)) |
| 219 | + |
| 220 | + && |
| 221 | + |
| 222 | + //right part of first and left part of second |
| 223 | + isScramble(s1.substr(i),s2.substr(0,n-i)) |
| 224 | + ); |
| 225 | + |
| 226 | + |
| 227 | + |
| 228 | + //if withswap give us right answer then we return true |
| 229 | + //otherwise the for loop do it work |
| 230 | + if(withswap) |
| 231 | + return true; |
| 232 | + //we are not returning false in else case |
| 233 | + //because we want to check further cases with the for loop |
| 234 | + } |
| 235 | + |
| 236 | + |
| 237 | + return mp[key] = false; |
| 238 | + |
| 239 | + } |
| 240 | +}; |
| 241 | + ``` |
| 242 | + </TabItem> |
| 243 | +</Tabs> |
| 244 | + |
| 245 | +## Solution Logic |
| 246 | + |
| 247 | +**1.Base Cases:**If the lengths of the two strings are not equal, they cannot be scrambled forms of each other, so return false. |
| 248 | +If the two strings are identical, they are trivially scrambled forms of each other, so return true. |
| 249 | +If the length of the string is 1 and the strings are not equal, return false. |
| 250 | +**2.Memoization:** Use a map mp to store already solved subproblems to avoid redundant computations. |
| 251 | +The key for the map is a combination of the two strings, represented as s1 + " " + s2. |
| 252 | +**3.Recursive Check:** Iterate over possible split points of the strings. |
| 253 | +For each split point, there are two cases to consider: |
| 254 | +1.Without swapping: |
| 255 | +Compare the left part of s1 with the left part of s2 and the right part of s1 with the right part of s2. |
| 256 | +2.With swapping: |
| 257 | +Compare the left part of s1 with the right part of s2 and the right part of s1 with the left part of s2. |
| 258 | +**4.Return Result:** If either of the conditions (with or without swapping) is satisfied, return true. |
| 259 | +If none of the conditions are satisfied after checking all possible split points, store the result as false in the memoization map and return false.1. |
| 260 | + |
| 261 | +## Time Complexity |
| 262 | + |
| 263 | + $O(N2)$. |
| 264 | + |
| 265 | +## Space Complexity |
| 266 | + |
| 267 | + $O(N2)$. |
| 268 | + |
| 269 | +## Resources |
| 270 | + |
| 271 | +- **GFG Problem:** [GFG Problem](https://www.geeksforgeeks.org/problems/scrambled-string/1) |
| 272 | +- **LeetCode Problem:** [LeetCode Problem](https://leetcode.com/problems/scramble-string/description/) |
| 273 | +- **Author's Geeks for Geeks Profile:** | [DaminiChachane](https://leetcode.com/u/divcxl15/) | |
| 274 | + |
| 275 | +This format ensures that all necessary details about the problem and its solution are clearly presented and easy to follow. |
0 commit comments