Description

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = “great”:

great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node “gr” and swap its two children, it produces a scrambled string “rgeat”.

rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t

We say that “rgeat” is a scrambled string of “great”.

Similarly, if we continue to swap the children of nodes “eat” and “at”, it produces a scrambled string “rgtae”.

rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a

We say that “rgtae” is a scrambled string of “great”.

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

Solution

 1 class Solution {
 2 public:
 3     bool isScramble(string s1, string s2) {
 4   		if (s1 == s2)
 5   			return true;
 6   		if (revserse_equal(s1, s2))
 7   			return true;
 8 
 9 		int len = s1.size();
10 
11   		int count[26];
12   		memset(count, 0, sizeof(int) * 26);
13   		for (int i = 0; i < len; ++ i){
14   			count[s1[i]-'a'] ++;
15   			count[s2[i]-'a'] --;
16   		}
17   		// check if the frequency of letters are the same in s1 and s2
18   		for (int i = 0; i < 26; ++ i) 
19   			if (count[i] )
20   				return false;
21   				
22   		if (len == 1)
23   			return true;  				
24 
25   		bool flg = false;
26   		for (int par = 1; par < len; ++ par){ // select the partition point
27   			flg = flg || judge(par, s1, s2);
28   			if (flg)
29   				return flg;
30   		}
31   		return flg;  		
32     }
33     bool judge(int par, string &s1, string &s2){
34         int len = s1.size();
35   		bool flg = isScramble(s1.substr(0, par), s2.substr(0, par)) && \
36   		isScramble(s1.substr(par, len - par),s2.substr(par, len - par));
37   		flg = flg || ( isScramble(s1.substr(0, par), s2.substr(len - par, par)) &&\
38   		 isScramble(s1.substr(par, len - par), s2.substr(0, len - par)) );
39   		return flg;
40     }
41     bool revserse_equal(string s1, string s2){
42     	for (int i = 0; i < s1.length(); ++ i){
43     		if (s1[i] != s2[s1.length()-1 - i])
44     			return false;
45     	}
46     	return true;
47     }
48 };

Analysis

This is a recursive solution. We iteratively select a partition point at each level and divide each string into two substrings. As we can swap the children of any non-leaf node, we have to judge recursively if

1.(Children not swapped) s1[0, par-1] == s2[0, par-1] AND s1[par, end] == s2[par, end]
2.(Children swapped) s1[0, par-1] == s2[len - par, end] AND s1[par, end] == s2[0, par-1]

S1 would be a SS of S2 if either of (1) and (2) is satisfied.

There also exists DP solution to this problem.

Comments