zoukankan      html  css  js  c++  java
  • 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 };
  • 相关阅读:
    mac上配置apidoc环境
    Yii 2.0 GII 访问404错误
    yii框架下使用redis
    PHPEXCEL读出数据是PHPExcel_RichText类型
    php实现仿百度分页
    apache的.htaccess文件作用和相关配置
    Yii2.0 解决“the requested URL was not found on this server”问题
    [基础与理论]C#变量
    基础&理论]C#的基本语法
    [基础&理论]C#的含义
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/8384450.html
Copyright © 2011-2022 走看看