leetcode[86] Scramble String
将一个单词按照这种方式分:
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的更多相关文章
- 【leetcode】Scramble String
Scramble String Given a string s1, we may represent it as a binary tree by partitioning it to two no ...
- [leetcode]87. Scramble String字符串树形颠倒匹配
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- [leetcode] 87. Scramble String (Hard)
题意: 判断两个字符串是否互为Scramble字符串,而互为Scramble字符串的定义: 字符串看作是父节点,从字符串某一处切开,生成的两个子串分别是父串的左右子树,再对切开生成的两个子串继续切开, ...
- [LeetCode] 87. Scramble String 搅乱字符串
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- [LeetCode] 87. Scramble String 爬行字符串
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- 【leetcode】 Scramble String (hard)★
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- Leetcode#87 Scramble String
原题地址 两个字符串满足什么条件才称得上是scramble的呢? 如果s1和s2的长度等于1,显然只有s1=s2时才是scramble关系. 如果s1和s2的长度大于1,那么就对s1和s2进行分割,划 ...
- 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 ...
- leetCode 87.Scramble String (拼凑字符串) 解题思路和方法
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
随机推荐
- Linux的selinux
SELinux 操作模式 学科 (Subject):SELinux 序,因此你能够将『主体』跟 process 划上等号: 目标 (Object): 主体程序是否能存取的『目标资源』一 ...
- Eclipse正在使用Ant扑灭Android数据包错误的解决方案 – Perhaps JAVA_HOME does not point to the JDK
问题描写叙述: 在Eclipse中执行ant批量打包工具出错,日志信息例如以下: D:\Android\android-sdk-windows\tools\ant\build.xml:601: The ...
- SpringAccess数据库(oracle)构造
陈科朝:http://blog.csdn.net/u013474104/article/details/44279309 ================ 1.spring 对数据库訪问的支持 当我们 ...
- hdu4717 The Moving Points 三分法
题意:坐标系上有n个点,每个点的坐标和移动方向速度告诉你,速度方向都是固定的.然后要求一个时刻,使得这个时刻,这些点中最远的距离最小. 做法:三分法,比赛的时候想不到.考虑两个点,如果它们走出来的路径 ...
- JS日期显示格式 yyyy-MM-dd hh:mm:ss
1.字符串转换为日期 Date.parse() 可以把 Date.toString() 和 Date.toUTCString()返回的字符串转换为日期类型 2.日期对象转换 ...
- C和指针 (pointers on C)——第三章——数据
第三章 数据 本章是非常重要的,在特定范围内使用.链接属性.存储类型.const.extern和statickeyword使用.几乎所有的公司是C++在采访的第一个问题. 总结: 具有external ...
- 我学的是设计模式的视频教程——装饰图案,装饰图案VS代理模式
课程视频 装饰模式 装饰模式VS代理模式1 装饰模式VS代理模式2 课程笔记 课程笔记 课程代码 课程代码 新课程火热报名中 课程介绍 版权声明:本文博主原创文章,博客,未经同意不得转载.
- Tyvj P1015 公路骑 (DP)
叙述性说明 Description 一个特殊的单行道都在每公里公交车站.们乘坐汽车的公里使来付费. 比如例子的第一行就是一个费用的单子. 没有一辆车子行驶超过10公里.一个顾客打算行驶n公里(1 ...
- LinkedBlockingQueue多线程测试
public class FillQueueThread extends Thread { private Queue queue; public FillQueueThread(Queue queu ...
- 数学思想方法-分布式计算-linux/unix技术基础(3)
夹: ~表示当前用户的主文件夹 .它代表了当前文件夹 ..它代表的父文件夹 链接文件 使用不同的文件名指的是相同的数据或程序.硬链接 在相同的物理文件系统,创建一个硬链接 -bash-4.2$ fin ...