- Scramble String
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.
Example
Example1
Input:
“great”
“rgeat”
Output:
true
Challenge
O(n3) time
解法1:
DFS搜索。参考网上答案。每次取i从1到len,取s1和s2的前前/尾尾和前尾/尾前部互相比较。
注意:
- 算hash值来剪枝节约时间。
- 关于时间复杂度。我认为是O(n^3)。因为s1和s2各有n ^ 2个子字符串,而子字符串的比较又需要O(n)。所以一共是O(n ^ 3)。欢迎指正。
代码如下:
class Solution {
public:
/**
* @param s1: A string
* @param s2: Another string
* @return: whether s2 is a scrambled string of s1
*/
bool isScramble(string &s1, string &s2) {
if (s1 == s2) return true;
int len1 = s1.size();
int len2 = s2.size();
if (len1 != len2) return false;
int hash1 = 0, hash2 = 0;
for (int i = 0; i < len1; ++i) {
hash1 += s1[i] - 'a';
hash2 += s2[i] - 'a';
}
if (hash1 != hash2) return false;
for (int i = 1; i < len1; ++i) {
string s11 = s1.substr(0, i);
string s21 = s2.substr(0, i);
string s12 = s1.substr(i);
string s22 = s2.substr(i);
if (isScramble(s11, s21) && isScramble(s12, s22))
return true;
s11 = s1.substr(len1 - i);
s21 = s2.substr(0, i);
s12 = s1.substr(0, len1 - i);
s22 = s2.substr(i);
if (isScramble(s11, s21) && isScramble(s12, s22))
return true;
}
return false;
}
};
解法2:DP。思想和解法1差不多,但用DP来实现。
dp[i][j][k]表示s1从第i个字符开始长度为k的子字符串和s2从第j个字符开始长度为k的子字符串是否为scramble。最后返回dp[0][0][n]。
计算顺序:
dp[i][j][1] //i is from 0…n, j is from 0…n
dp[i][j][2] …
dp[i][j][n] …
计算时间复杂度O(n ^ 4),空间复杂度O(n ^ 3)。
代码如下:
class Solution {
public:
/**
* @param s1: A string
* @param s2: Another string
* @return: whether s2 is a scrambled string of s1
*/
bool isScramble(string &s1, string &s2) {
if (s1 == s2) return true;
int n = s1.size();
int n2 = s2.size();
if (n != n2) return false;
vector<vector<vector<bool>>> dp(n, vector<vector<bool>>(n, vector<bool>(n + 1, false)));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (s1[i] == s2[j]) dp[i][j][1] = true;
}
}
for (int k = 2; k <= n; ++k) { // k is the len of the substring
for (int i = 0; i <= n - k; ++i) {
for (int j = 0; j <= n - k; ++j) {
for (int w = 1; w < k; ++w) { //note: not w <= k
if (dp[i][j][w] && dp[i + w][j + w][k - w]) {
dp[i][j][k] = true;
break;
}
if (dp[i][j + k - w][w] && dp[i + w][j][k - w]) {
dp[i][j][k] = true;
break;
}
}
}
}
}
return dp[0][0][n];
}
};