将一个单词按照这种方式分:

Below is one possible representation of s1 = "great":

    great
/ \
gr eat
/ \ / \
g r e at
/ \
a t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".

    rgeat
/ \
rg eat
/ \ / \
r g e at
/ \
a t

We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae
/ \
rg tae
/ \ / \
r g ta e
/ \
t a

We say that "rgtae" is a scrambled string of "great".

这样就说他们是scrambled string。现在给你两个字符串怎么判断是否属于scrambled string呢

思路:

想了n久,木有什么好的idea。

然后学习了justdoit兄的博客,理解了后自己也跟着写了个递归的。

简单的说,就是s1和s2是scramble的话,那么必然存在一个在s1上的长度l1,将s1分成s11和s12两段,同样有s21和s22。
那么要么s11和s21是scramble的并且s12和s22是scramble的;
要么s11和s22是scramble的并且s12和s21是scramble的。

判断剪枝是必要的,否则过不了大数据集合。

class Solution {
public:
bool subScramble(string s1, string s2)
{
if (s1 == s2) return true;
int len = s1.size();
string sort_s1 = s1, sort_s2 = s2;
sort(sort_s1.begin(), sort_s1.end());
sort(sort_s2.begin(), sort_s2.end());
if (sort_s1 != sort_s2) return false; //如果字母不相等直接返回错误
for (int i = ; i < len; ++i)
{
string s1_left = s1.substr(,i);
string s1_right = s1.substr(i);
string s2_left = s2.substr(,i);
string s2_right = s2.substr(i); if (subScramble(s1_left, s2_left) && subScramble(s1_right, s2_right))
return true; s2_left = s2.substr(, len - i);
s2_right = s2.substr(len - i); if (subScramble(s1_left, s2_right) && subScramble(s1_right, s2_left))
return true;
}
return false;
}
bool isScramble(string s1, string s2)
{
return subScramble(s1, s2);
}
};

如果有更好的方法,我们一般是不用递归的,因为递归往往复杂以致难以掌控。继续学习,发现果然有动态规划的方法。凭空想,确实难以想象。但看见之后又恍然明了。

本题递归复杂度是非多项式的。具体多少您探讨一下。动态规划的复杂度应该是O(n^4),连动态规划都这个复杂度了,可见此题之可怕啊。

三维动态规划:

dp[k][i][j]: s1的第i个开始长度为k的串和s2的第j个开始长度为k的串是否scrambled,是的话true,否则存false;

同递归核心思想,dp[k][i][j]应该可以从1到k-1长度的分割来求解,一旦有一个为true,那么dp[k][i][j]就为true并跳出。

即:

dp[k][i][j] = (dp[div][i][j] && dp[k-div][i+div][j+div] || dp[div][i][j+k-div] && dp[k-div][i+div][j]);

div从1到k-1,分两种情况,即s1的从i开始的div个和s2从j开始的div个scrambled并且从i+div开始的k-div个都匹配那么true,

同理,如果s1的i开始的div个和s2的后div个匹配以及剩下另外两部分也都匹配,那么true。直到找到true位置。如下代码,找到true后,for中的判断!dp[k][i][j]不成立就跳出了。

class Solution {
public:
// 动态规划 dp[k][i][j]存s1从第i个开始长度为k的串和s2从j开始长度为k的串是否scrambled
bool isScramble(string s1, string s2)
{
if (s1.size() != s2.size()) return false;
int len = s1.size();
bool dp[len+][len][len]; // initialization
for (int i = ; i < len; ++i)
for (int j = ; j < len; ++j)
dp[][i][j] = s1[i] == s2[j]; // dp
for (int k = ; k < len + ; ++k)
for (int i = ; i < len; ++i)
for (int j = ; j < len; ++j)
{
// initialization
dp[k][i][j] = false;
// once dp[k][i][j] is true, jump out
for (int div = ; div < k && !dp[k][i][j]; ++div)
dp[k][i][j] = (dp[div][i][j] && dp[k-div][i+div][j+div] || dp[div][i][j+k-div] && dp[k-div][i+div][j]);
}
return dp[len][][];
}
};

以下三点值得注意:

1. 此题递归只要主要判断排序后子串是否相等,不等直接剪枝,减少计算量。

2. 两中方法都用到的核心是把两个字符串都分成两部分,如果对应匹配或者交叉匹配满足,则true。

3. 就是substr的用法,如何准确判断子串。

leetcode[86] Scramble String的更多相关文章

  1. 【leetcode】Scramble String

    Scramble String Given a string s1, we may represent it as a binary tree by partitioning it to two no ...

  2. [leetcode]87. Scramble String字符串树形颠倒匹配

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  3. [leetcode] 87. Scramble String (Hard)

    题意: 判断两个字符串是否互为Scramble字符串,而互为Scramble字符串的定义: 字符串看作是父节点,从字符串某一处切开,生成的两个子串分别是父串的左右子树,再对切开生成的两个子串继续切开, ...

  4. [LeetCode] 87. Scramble String 搅乱字符串

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  5. [LeetCode] 87. Scramble String 爬行字符串

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  6. 【leetcode】 Scramble String (hard)★

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  7. Leetcode#87 Scramble String

    原题地址 两个字符串满足什么条件才称得上是scramble的呢? 如果s1和s2的长度等于1,显然只有s1=s2时才是scramble关系. 如果s1和s2的长度大于1,那么就对s1和s2进行分割,划 ...

  8. leetcode@ [87] Scramble String (Dynamic Programming)

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  9. leetCode 87.Scramble String (拼凑字符串) 解题思路和方法

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

随机推荐

  1. hdu 1814 Peaceful Commission (2-sat 输出字典序最小的路径)

    Peaceful Commission Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  2. 迷宫的最短路径 (BFS)

    N*M的迷宫,从起点到终点,求最短距离 宽度优先搜索按照距开始状态由近及远的顺序进行搜索,因此可以很容易的用来求最短路径,最少操作之类问题的答案.  (可以构造成pair或者编码成int来表达状态) ...

  3. 使用JAVA打开本地应用程序相关的文件

    在该项目中需要运行本地文件或应用程序,JDK6添加后Desktop类别.可以直接使用.这使得有可能在程序中无论什么应用程序可以打开的.例:打开pdf文件,当地福昕是默认打开.执行程序将使用福昕开放pd ...

  4. Ubuntu下怎样切换到ROOT登录

    原文:http://james23dier.iteye.com/blog/721246 近期一直在学习linux,选择ubuntu作为联系的操作系统.然后一直发现自己所创建的用户和root用户不是一个 ...

  5. Codeforces Round #243 (Div. 1)-A,B,C-D

    此CF真是可笑.. . 由于早晨7初始点,因此,要做好CF时间已经17没有休息一小时,加上中午5小时耐力赛. 心里很清楚.是第一个问题的时候,几乎被解读为寻求最大的领域和.然后找到一个水体,快速A降. ...

  6. 2014联合三所学校 (HDU 4888 HDU 4891 HDU 4893)

    HDU 4891 The Great Pan 注册标题  他怎么说,你怎么样  需要注意的是乘法时,它会爆炸int 代码: #include<iostream> #include<c ...

  7. Mac下Android配置及unity3d的导出Android

    昨晚实在弄的太晚了,费尽脑汁才弄出来. ok,关于mac下的eclipse的安卓配置,我仅仅贴一个网址,就ok了 http://developer.android.com/sdk/index.html ...

  8. TCP通信中的大文件传送

    TCP通信中的大文件传送 源码   (为节省空间,不包含通信框架源码,通信框架源码请另行下载) 文件传送在TCP通信中是经常用到的,本文针对文件传送进行探讨 经过测试,可以发送比较大的文件,比如1个G ...

  9. MySql绿色版配置及使用详解

    原文:MySql绿色版配置及使用详解 最近在做项目开发时用到了MySql数据库,在看了一些有关MySql的文章后,很快就上手使用了.在使用的过程中还是出现了一些问题,因为使用的是绿色免安装版的MySq ...

  10. 关于重写ID3 Algorithm Based On MapReduceV1/C++/Streaming的一些心得体会

    心血来潮,同时想用C++连连手.面对如火如荼的MP,一阵念头闪过,如果把一些ML领域的玩意整合到MP里面是不是很有意思 确实很有意思,可惜mahout来高深,我也看不懂.干脆自动动手丰衣足食,加上自己 ...