class Solution {
unordered_map<int, bool> dp;
bool dfs(const string& s1, const string& s2, int id1, int id2, int len) {
if (len == 1) {
return true;
} else if (len == 0) {
return false;
}
int key = id1*900 + id2*30 + len;
if (dp.count(key)) return dp[key];
vector<int> d1(26, 0), d2(26, 0), d3(26, 0);
for (int i = 0; i < len - 1; ++i) {
int a1 = s1[id1 + i] - 'a', a2 = s2[id2 + i] - 'a', a3 = s2[id2 + len - i - 1] - 'a';
d1[a1]++;
d2[a2]++;
d3[a3]++;
bool same12 = true;
for (int i = 0; i < 26 && same12; ++i) {
if (d1[i] != d2[i])
same12 = false;
}
bool same13 = true;
for (int i = 0; i < 26 && same13; ++i) {
if (d1[i] != d3[i])
same13 = false;
}
if (same12) {
if (dfs(s1, s2, id1, id2, i + 1) && dfs(s1, s2, id1 + i + 1, id2 + i + 1, len - i - 1)) {
dp[key] = true;
return true;
}
}
if (same13) {
if (dfs(s1, s2, id1, id2 + len - i - 1, i + 1) && dfs(s1, s2, id1 + i + 1, id2, len - i - 1)) {
dp[key] = true;
return true;
}
}
}
dp[key] = false;
return false;
}
public:
bool isScramble(string s1, string s2) {
vector<int> d(26, 0);
for (auto c: s1)
d[c - 'a']++;
for (auto c: s2)
d[c - 'a']--;
for (auto n: d) if (n != 0) return false;
return dfs(s1, s2, 0, 0, s1.size());
}
};