Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
题目:给定两个字符串,判断他们是否为Scramble String。
Scramble String的含义为:长度相等的两个字符串s1,s2,从某一位置切开s1,s1左侧与s2左侧(或右侧)相同长度的子串为Scramble String,并且s1右侧与s2右侧(或左侧)相同长度的子串为Scramble String。
从上面的定义可以很容易想到递归算法:即按照一定长度分割s1,s2,递归判断左右子串是否为Scramble String。
一、递归法:
代码如下:
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1==s2) return true;
if(s1.length()!=s2.length()) return false;
for(int i=1;i<s1.length();i++){
if((isScramble(s1.substr(0,i),s2.substr(0,i))&&isScramble(s1.substr(i),s2.substr(i)))||(isScramble(s1.substr(0,i),s2.substr(s2.length()-i))&&isScramble(s1.substr(i),s2.substr(0,s2.length()-i)))){
return true;
}
}
return false;
}
};
结果发现超时了,上网查看后发现了
剪枝法,就是在递归前判断两子串字符是否相同,即对字符串中字符计数。
代码如下:
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1==s2) return true;
if(s1.length()!=s2.length()) return false;
int judge[26]={0};
for(int i=0;i<s1.length();i++){
judge[s1[i]-'a']++;
judge[s2[i]-'a']--;
}
for(int i=0;i<26;i++){
if(judge[i]!=0) return false;
}
for(int i=1;i<s1.length();i++){
if((isScramble(s1.substr(0,i),s2.substr(0,i))&&isScramble(s1.substr(i),s2.substr(i)))||(isScramble(s1.substr(0,i),s2.substr(s2.length()-i))&&isScramble(s1.substr(i),s2.substr(0,s2.length()-i)))){
return true;
}
}
return false;
}
};
成功通过~
二、DP算法:
通过后想挑战一下DP算法。
这里使用了dp变量dp[i][j][len],它的含义为s1从i开始的长度为len的子串与s2从j开始的长度为len的子串是否为Scramble String。
初始化dp[i][j][1],依据为s1[i]是否等于s2[j];当len为2 时,dp[i][j][2]的计算方法为dp[i][j][1]&&dp[i+1][j+1][1]||dp[i][j+1][1]&&dp[i+1][j][1];以此类推,当len为n时,dp[i][j][n]的计算方法为dp[i][j][k]&&dp[i+k][j+k][len-k]||dp[i][j+len-k][k]&&dp[i+k][j][len-k]。
代码如下:
class Solution {
public:
bool isScramble(string s1, string s2) {
int l=s1.length();
bool ***dp=new bool**[l];
for(int i=0;i<l;i++){
dp[i]=new bool*[l];
}
for(int i=0;i<l;i++){
for(int j=0;j<l;j++){
dp[i][j]=new bool[l+1];
memset(dp[i][j],0,l+1*sizeof(bool));
dp[i][j][1]=s1[i]==s2[j];
}
}
for(int length=2;length<=l;length++){
for(int i=0;i<=l-length;i++){
for(int j=0;j<=l-length;j++){
for(int k=1;k<length;k++){
dp[i][j][length]=dp[i][j][length]||(dp[i][j][k]&&dp[i+k][j+k][length-k])||(dp[i][j+length-k][k]&&dp[i+k][j][length-k]);}
}
}
}
return dp[0][0][l];
}
};