牛客网->在线编程->letcode->scramble-string
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 ofs1 ="great":
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".
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".
We say that"rgtae"is a scrambled string of"great".Given two stringss1 ands2 of the same length, determine if s2 is a scrambled string ofs1.
刚开始拿到题目并没有用到DP,做了一个全局搜索,结果超时了。也先写一下我的思路,再贴一下参考别人的DP大神代码。我的思路:先用数字表示字符串,方便讲解,
定义:
1、切点,要将一个字符串变成两个非空二叉树,则需要将在字符串中间插空切下去,比如str1=“1234”就有12之间、23之间、34之间三个切点;后面根据切点的从左到右的顺序命名为:cut[i];
切点 | 左子树 | 右子树 | 是否可行 |
cut[0] | 3 | 142 | 否(左子树范围[3]与右子树[1,4]范围交叉) |
cut[1] | 31 | 42 | 否(左子树范围[1,3]与右子树[2,4]范围交叉) |
cut[2] | 314 | 2 | 否(左子树范围[1,4]与右子树[2]范围交叉) |
(其实已经构造出了最优子结构,动态规划的核心。但是由于对这种不是一维二维的动态规划见得少,没有做出来。。)我的代码就是这种深搜,最后超时。不知道代码有没有什么BUG,自己测了一些还没测出问题
map > tab,rtab;
map flag;
string ss;
void clear(map &tmp){
map::iterator it;
for(it=tmp.begin(); it!=tmp.end(); it++)
it->second = 0;
}
//功能:返回从左向右搜索,下一个可能切点的位置
//形参:s2是str2二叉树的某一个子树,left、right为在原str2的左右界限,pos为开始搜索位置
int c_find(const string &s2,int left,int right,int pos){
if(pos>right)
return right;
int i=left, j=pos;
clear(flag);
do{
int tmp;
do{
tmp = tab[s2[i-left]][flag[s2[i-left]]];
if(tmp==-1 || tmp>=right)
return right;
}while(flag[s2[i-left]]++,tmpright);
j = min(j, tmp);
//flag[s2[i-left]]++;
}while(i++<(right-j));
return j;
}
bool scramble_judge(const string &s1,const string &s2,int left,int right){
//cout< char_set;
for(int i=0; i::iterator it;
for(it=char_set.begin(); it!=char_set.end(); it++){
flag[*it] = 0;
tab[*it] = vector(len1+1,-1);
int j=0;
for(int i=0; i(len1+1,-1);
int j=0,k=-1;
while((tab[*it])[++k] != -1);
while(k){
(rtab[*it])[j++] = (tab[*it])[--k];//str2某个字符在str1中出现的位置(存储顺序为递减)
}
}
return scramble_judge(s2, s2, 0, len1-1);
}
别人的动态规划算法:dp[k][i][j]表示str1从i开始长度为k,与str2从j开始长度为k的子串是否为scramble-string
bool isScramble(string s1, string s2) {
int len1=s1.size(), len2=s2.size();
if(len1 != len2)
return false;
//相当于 bool dp[len1][len1][len1];
vector > > dp(len1, vector>(len1,vector(len1,false)) );
//初始化数组,子串长度为一时,只要相等就是
for(int i=0; i