首页 > 代码库 > Leetcode#87 Scramble String

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,面试的时候别忘了啊。

Leetcode#87 Scramble String