给出长度相同的两个字符串是s1,s2,判断是否可以通过扰乱字符串s1得到字符串s2;
扰乱字符串的规则是
1.随机将字符串分为两个不为空的字符串
可以进行两种操作
1)保持原状
2)交换两个字符串的位置
2.继续执行1操作,字符串长度为1,算法停止
不能通过扰乱字符串s1得到s2
则
如果能通过扰乱字符串s1得到s2
则一定有两种情况
s1在i处分割得到l(s1)和r(s1)
1)若是通过s1保持原状得到s2,将s2在i处分割,得到l(s2)和r(s2) ,则可以扰乱l(s1)得到l(s2) ,可以扰乱r(s1)得到r(s2)
1)若是通过s1交换两个子字符串得到s2,将s2在lenght-i处分割,得到l(s2)和r(s2) ,则可以扰乱l(s1)得到r(s2) ,可以扰乱r(s1)得到l(s2)
class Solution {
private:
// 记忆化搜索存储状态的数组
// -1 表示 false,1 表示 true,0 表示未计算
int memo[30][30][31];
string s1, s2;
public:
bool Check_num(int l1,int l2,int lenght) {
unordered_map<char, int>p;
for (int i = l1; i < l1 + lenght; i++) {
p[s1[i]]++;
}
for (int i = l2; i < l2 + lenght; i++) {
p[s2[i]]--;
}
if (any_of(p.begin(), p.end(), [](const auto& w) {return w.second != 0; }))
{
return false;
}
return true;
}
bool dfs(int l1, int l2, int lenght) {
if (memo[l1][l2][lenght])
return memo[l1][l2][lenght] == 1;
if (s1.substr(l1, lenght) == s2.substr(l2, lenght))
return true;
if (!Check_num(l1,l2,lenght)) {
return false;
}
for (int i = 1; i < lenght; i++) {
if (dfs(l1, l2, i) && dfs(l1 + i, l2 + i, lenght - i)) {
memo[l1][l2][lenght] = 1;
return true;
}
if (dfs(l1, l2 + lenght - i, i) && dfs(l1 + i, l2, lenght - i)) {
memo[l1][l2][lenght] = 1;
return true;
}
}
memo[l1][l2][lenght] = -1;
return false;
}
bool isScramble(string s1, string s2) {
memset(memo, 0, size(memo));
this->s1 = s1;
this->s2 = s2;
return dfs(0, 0, s1.size());
}
};