字符串可二分并交换左右
字符串可不断二分,并随意交换左右子树,构成扰动。判断一个串是否是另一个串的扰动。
bool isScramble(string s1, string s2) {
// 设dp[n][i][j]表示两个等长串s1[i..i+n)和s2[j..j+n)是否scramble
// 每个串可由二叉树分成两部分,遍历左串长1<=k<n的划分
// | k | n-k |、| k | n-k | 或 | k | n-k |、| n-k | k |
// dp[n][i][j] = ( dp[k][i][j] && dp[n-k][i+k][j+k] ) || ( dp[k][i][j+n-k] && dp[n-k][i+k][j] )
// 初始n==1时,dp[1][i][j] = s1[i]==s2[j]
const int N = s1.size();
if (N != s2.size()) return false;
vector<vector<vector<bool>>> dp(N + 1, vector<vector<bool>>(N, vector<bool>(N, false)));
// n==1
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
dp[1][i][j] = s1[i] == s2[j];
}
}
for (int n = 2; n <= N; n++) {
for (int i = 0; i + n <= N; i++) {
for (int j = 0; j + n <= N; j++) {
for (int k = 1; k < n && !dp[n][i][j]; k++) {
dp[n][i][j] = ( dp[k][i][j] && dp[n-k][i+k][j+k] )
|| ( dp[k][i][j+n-k] && dp[n-k][i+k][j] );
}
}
}
}
return dp[N][0][0];
}