使用下面描述的算法可以扰乱字符串 s 得到字符串 t :
如果字符串的长度为 1 ,算法停止
如果字符串的长度 > 1 ,执行下述步骤:
在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。
随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x 。
在 x 和 y 这两个子字符串上继续从步骤 1 开始递归执行此算法。
给你两个 长度相等 的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。如果是,返回 true ;否则,返回 false 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/scramble-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
import java.util.Scanner;
class Solution {
private static boolean isOk(char[] str1, char[] str2, int L1, int L2, int length, int[][][] dp) {
if (dp[L1][L2][length] != -1) {
return dp[L1][L2][length] == 1;
}
if (length == 1) {
return str1[L1] == str2[L2];
}
for (int i = 1; i < length; ++i) {
if (isOk(str1, str2, L1, L2, i, dp) && isOk(str1, str2, L1 + i, L2 + i, length - i, dp)) {
dp[L1][L2][length] = 1;
return true;
}
if (isOk(str1, str2, L1, L2 + length - i, i, dp) && isOk(str1, str2, L1 + i, L2, length - i, dp)) {
dp[L1][L2][length] = 1;
return true;
}
}
dp[L1][L2][length] = 0;
return false;
}
public static boolean isScramble(String s1, String s2) {
if (s1 == null || s1.length() == 0 || s2 == null || s2.length() == 0) {
return false;
}
if (s1.length() != s2.length()) {
return false;
}
if (s1.equals(s2)) {
return true;
}
char[] str1 = s1.toCharArray();
char[] str2 = s2.toCharArray();
int[] map = new int[256];
for (int i = 0; i < str1.length; ++i) {
map[str1[i]]++;
}
for (int i = 0; i < str2.length; ++i) {
if (--map[str2[i]] < 0) {
return false;
}
}
int[][][] dp = new int[str1.length][s1.length()][str1.length + 1];
for (int i = 0; i < s1.length(); ++i) {
for (int j = 0; j < s2.length(); ++j) {
for (int k = 0; k <= s1.length(); ++k) {
dp[i][j][k] = -1;
}
}
}
return isOk(str1, str2, 0, 0, str1.length, dp);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String str1 = in.next();
String str2 = in.next();
System.out.println(isScramble(str1, str2));
}
}
}