Leetcode#87 Scramble String
两个字符串满足什么条件才称得上是scramble的呢?
如果s1和s2的长度等于1,显然只有s1=s2时才是scramble关系。
如果s1和s2的长度大于1,那么就对s1和s2进行分割,划分成两个子问题分别处理。
如何分割呢?当然不能任意分割。假设分割后s1变成了s11和s12,s2变成了s21和s22,那么只有2种分割方式:
1. s11.length = s21.length & s12.length = s22.length,如下图所示:
s1: ? ? ? ? ?
----- ---
s11 s12
s2: ? ? ? ? ?
----- ---
s21 s22
2. s11.length = s22.length & s12.length = s21.length,如下图所示:
s1: ? ? ? ? ?
----- ---
s11 s12
s2: ? ? ? ? ?
--- -----
s21 s22
经过分割后,我们可以得到长度相等的两组子串,正好是两个子问题。于是就可以递归分割下去了,直到两个串的长度长度为1停止分割。
令scramblep[i][j][k]表示s1[i..i+k]和s2[j..j+k]相互之间是否是scramble关系,即i是s1的子串起始位置,j是s2的子串起始位置,k是子串的长度。则有如下递推公式:
scramblep[i][j][k] = (scramblep[i][j][t] && scramblep[i+t][j+t][k-t]) || (scramblep[i][j+k-t][t] && scramblep[i+t][j][k-t]),其中0 < t < k
(正好对应上面说的两种分割方式)
初值为:scramblep[i][j][k] = s1[i..i+k] == s2[j..j+k],(如果两个子串相等,自然是scramble关系。这个初值包含了长度为1的情况)
代码:
1 bool isScramble(string s1, string s2) { 2 if (s1.length() != s2.length()) return false; 3 if (s1.empty()) return true; 4 5 int len = s1.length(); 6 bool ***judge = new bool**[len]; 7 for (int i = 0; i < len; i++) { 8 judge[i] = new bool*[len]; 9 for (int j = 0; j < len; j++) 10 judge[i][j] = new bool[len + 1]; 11 } 12 13 for (int k = 1; k <= len; k++) { 14 for (int i = 0; i + k <= len; i++) { 15 for (int j = 0; j + k <= len; j++) { 16 judge[i][j][k] = s1.substr(i, k) == s2.substr(j, k); 17 for (int t = 1; t < k && !judge[i][j][k]; t++) { 18 judge[i][j][k] |= judge[i][j + k - t][t] && judge[i + t][j][k - t]; 19 judge[i][j][k] |= judge[i][j][t] && judge[i + t][j + t][k - t]; 20 } 21 } 22 } 23 } 24 25 return judge[0][0][len]; 26 }
new出来的内存都没有delete,面试的时候别忘了啊。