Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
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"
.
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
参考博文:http://www.cnblogs.com/easonliu/p/3696135.html
这道题与其说是DP更不如说是一道大递归。
因为题设给了一个二叉树的结构,而这个结构是递归定义的,更让人容易想起递归解法。
对于递归思路,自然是应当从小数据开始,例如长度为0、1、2等等。其实动态规划也是一样的,一个大问题分解为子问题才能找到问题的本质。
递归的思路如下:
(1)长度为1的时候,return s1==s2
(2)长度>1的时候,首先需要判断两个字符串包含的字符集是否相同,参考博文给了一种非常给力的剪枝即是如此。利用srot函数将整个字符串进行排序并比较,如果不相等则返回false。这是一个巨大的剪枝,也正因如此这样的递归才可以通过。
(3)长度>1的时候,将串分解成2个子串。s1、s2分别分解为a1a2和b1b2,需要判断a1==b1&&a2==b2 或者 a1==b2 && a2==b1。这里有非常重要的一点是在求子字符串的时候,需要注意判断之前要控制长度相等,否则会一直re的。
class Solution {
public:
bool isScramble(string s1, string s2) {
int m=s1.size();
int n=s2.size();
if(m!=n) return false;
if(m==0) return true;
if(m==1) return s1==s2;
//要求字符集相同
string temp1=s1,temp2=s2;
sort(temp1.begin(),temp1.end());
sort(temp2.begin(),temp2.end());
if(temp1!=temp2) return false;
bool result=false;
for(int i=1;i<m && !result;i++){
//以前i个字符进行分割
string t11=s1.substr(0,i);
string t12=s1.substr(i);
string t21=s2.substr(0,i);
string t22=s2.substr(i);
result=isScramble(t11,t21) && isScramble(t12,t22);
if(!result){
//以后i个字符进行分割
string t21=s2.substr(0,m-i);
string t22=s2.substr(m-i);
result=isScramble(t11,t22) && isScramble(t12,t21);
}
}
return result;
}
};
至于动归的解法,网上给出的是一个3维DP。
这里可以讨论一下DP的维度如何确定
一般而言,我们需要观察问题中有多少个独立变化的变量,那么DP的维度就是几维。
例如之前的乌龟棋问题,有4张牌+位置,正常思路肯定是5维,但是由于走过的路程严格等于4张牌对应维度的值进行运算得到,故该问题可以缩减为4维DP。
这个问题中,s1和s2下标本身肯定是独立变化的毋庸置疑,设置为i,j
最后一维比较难想也比较关键,利用k表示子字符串的长度,表示s1[i..i+k] s2[j..j+k]二者可以相互变化。
具体代码先研究一下吧…毕竟这题递归这么明显比较难想到