87. Scramble String

▶ 将一个单词 W1 以字母为最小单位拆成一棵二叉树,旋转其中的某几个结点的左右子树,再拼装回去得到单词 W2,我们称 W1 与 W2 等价。现在给出两个单词,判定他们是否等价。

● 代码,4 ms,递归,最快的解法算法与之相同。有方法利用 unordered_map 缓存了各子串的判定结果,但由于子串情况数较多,反而减速为 75 ms

 1 class Solution
 2 {
 3 public:
 4     bool isScramble(string s1, string s2)
 5     {
 6         if (s1 == s2)// 先做一些简单的比较,诸如字符数、每种字符的个数
 7             return true;
 8         if (s1.size() != s2.size())
 9             return false;
10         int i, len, count[26] = { 0 };
11         for (i = 0, len = s1.size(); i < len; i++)
12         {
13             count[s1[i] - 'a']++;
14             count[s2[i] - 'a']--;
15         }
16         for (i = 0; i < 26; i++)
17         {
18             if (count[i])
19                 return false;
20         }
21         for (i = 1; i <= len - 1; i++)
22         {
23             if (isScramble(s1.substr(0, i), s2.substr(0, i)) && isScramble(s1.substr(i), s2.substr(i)))// 前半段跟前半段比,后半段跟后半段比
24                 return true;
25             if (isScramble(s1.substr(0, i), s2.substr(len - i)) && isScramble(s1.substr(i), s2.substr(0, len - i)))// 前半段跟后半段比,后半段跟前半段比
26                 return true;
27         }
28         return false;
29     }
30 };

 ● 代码,41 ms,三维动态规划,时间复杂度 O(n4)

 1 class Solution
 2 {
 3 public:
 4     bool isScramble(string s1, string s2)
 5     {
 6         const int sSize = s1.size();
 7         int len, i, j, k;
 8         if (sSize == 0)
 9             return true;
10         if (sSize == 1)
11             return s1 == s2;
12         vector<vector<vector<bool>>> isS(sSize + 1, vector<vector<bool>>(sSize, vector<bool>(sSize, false)));
13             // sS[i][j][k] 表示的是从 s1[j] 和 s2[k] 开始的长为 i 的子串,是否等价
14         for (i = 0; i < sSize; i++)
15         {
16             for (j = 0; j < sSize; j++)
17                 isS[1][i][j] = s1[i] == s2[j];
18         }
19         for (len = 2; len <= sSize; len++)// 每次循环填充一层
20         {
21             for (i = 0; i <= sSize - len; i++)
22             {
23                 for (j = 0; j <= sSize - len; j++)
24                 {
25                     for (k = 1; k < len && !isS[len][i][j]; k++)
26                     {
27                         isS[len][i][j] = isS[len][i][j] || (isS[k][i][j] && isS[len - k][i + k][j + k]);
28                         isS[len][i][j] = isS[len][i][j] || (isS[k][i + len - k][j] && isS[len - k][i][j + k]);
29                     }
30                 }
31             }
32         }
33         return isS[sSize][0][0];
34     }
35 };

 ● 动态规划的另一个版本,31 ms

 1 class Solution
 2 {
 3 public:
 4     bool isScramble(string s1, string s2)
 5     {
 6         if (s1.size() != s2.size())
 7             return false;
 8         const int len = s1.length();        
 9         vector<vector<vector<bool>>> F(len, vector<vector<bool>>(len, vector<bool>(len + 1, false)));
10         // F(i, j, k) 表示从s1[i] 和 s2[j] 开始的长为 k 的子串是否等价
11         // 使用长度 q 来切割上述子串(q < k),分前半段、后半段分别对应的两种情况进行讨论       
12         // s1 [   x1    |         x2         ]
13         //    i         i + q                i + k - 1
14         // s2 [   y1    |         y2         ]
15         //    j         j + q                j + k - 1
16         // s2 [       y1        |     y2     ]
17         //    j                 j + k - q    j + k - 1
18         // 对于 k = 1,仅需检验 s1[i] 和 s2[j] 
19         // 对于 k > 1 和 1 <= q < k,需要讨论 F(i, j, k) = (F(i, j, q) && F(i + q, j + q, k - q)) || (F(i, j + k - q, q) && F(i + q, j, k - q));       
20         for (int k = 1; k <= len; ++k)
21         {
22             for (int i = 0; i + k <= len; ++i)
23             {
24                 for (int j = 0; j + k <= len; ++j)
25                 {
26                     if (k == 1)
27                         F[i][j][k] = s1[i] == s2[j];
28                     else
29                     {
30                         for (int q = 1; q < k && !F[i][j][k]; ++q)
31                         {
32                             F[i][j][k] = (F[i][j][q] && F[i + q][j + q][k - q]) || (F[i][j + k - q][q] && F[i + q][j][k - q]);
33                         }
34                     }
35                 }
36             }
37         }
38         return F[0][0][len];
39     }
40 };
原文地址:https://www.cnblogs.com/cuancuancuanhao/p/8384450.html