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.
const int MAX = 100 + 10;
int dp[MAX][MAX][MAX];
class Solution {
public:
string s1,s2;
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size())return false;
this->s1 = s1;
this->s2 = s2;
for(int i = 0; i < s1.size(); i++)
for(int j = 0; j < s2.size(); j++)
for(int len = 1; len <= s1.size(); len++)
dp[i][j][len] = -1;
return match(0,0,s1.size());
}
bool match(int idx1, int idx2, int len)
{
if(dp[idx1][idx2][len] != -1)return dp[idx1][idx2][len];
if(len == 1)
{
dp[idx1][idx2][len] = s1[idx1] == s2[idx2];
return dp[idx1][idx2][len];
}
for(int l = 1; l < len; l++)
{
if((match(idx1, idx2, l) && match(idx1 + l, idx2 + l, len - l)) ||
(match(idx1, idx2 + len - l, l) && match(idx1 + l, idx2, len - l)))
{
dp[idx1][idx2][len] = 1;
return 1;
}
}
dp[idx1][idx2][len] = 0;
return false;
}
};