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

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. msys2 安装注意事项

    它一直在使用 msys.有一个最近发现 msys2.而且msys2 配套的编译器是MinGW-w64. 就试着用了用,感觉还不错,这里把安装过程记录一下. 简单的说,MSYS2 是MSYS的一个升级版 ...

  2. HTTPS抓包配置

    以Charles为例 配置Charles抓取Https需要手机和PC分别进行配置. 步骤: 1.PC下载charles客户端,并安装. 2.charles客户端安装证书 注意证书安装需要保存在&quo ...

  3. HMAC-SHA1算法签名及Authorization头认证

    使用PHP进行HMAC-SHA1签名,并通过Authorization头认证Deom $app_id = 'id'; $host = "test.abc.com"; $port = ...

  4. a^b%c 的三种形式

    求a^b%c,(1  <= a,b <= 2^62, 1 <= c <= 10^9) 最主要的高速幂 _LL mod_exp(_LL a, _LL b, int c) { _L ...

  5. JS数据绑定模板artTemplate试用

    之前写JS绑定数据曾经用过tmpl库,虽然功能比较强大但是感觉不是很轻量,对于相对简单的数据需求显得有些臃肿.而Ajax返回数据自己拼接html的方式又显得不够高端,因此今天看了一篇介绍artTemp ...

  6. SQL Server 2005 MD5函数

    原文:SQL Server 2005 MD5函数 在SQL Server 2005下自带的函数HashBytes() ,此函数是微软在SQL Server 2005中提供的,可以用来计算一个字符串的M ...

  7. 基于Android的ELF PLT/GOT符号和重定向过程ELF Hook实现(by 低端农业代码 2014.10.27)

    介绍 技术原因写这篇文章,有两种: 一个是在大多数在线叙述性说明发现PLT/GOT第二十符号重定向过程定向x86的,例<Redirecting functions in shared ELF l ...

  8. AspNetPager常用属性及一些样式

    AlwaysShow 总是显示分页控件,即使要分页的数据只有一页 AlwaysShowFirsLastPageNumbr 是否总是显示第一页和最后一页数字页索引按钮 BackImageUrl 面板的背 ...

  9. Swift初体验(两)

    // 写功能初体验 func getMyName(firstName first:String, lastName last:String) -> String{ //return first ...

  10. MVC中实现多按钮提交(转)

    有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能,比如一个简单的审批功能. 如果是用webform那不需要讨论,但asp.net mvc中一个表单只能提交到一个Action处理,相对比较 ...