• [LeetCode] Scramble String 字符串 dp


    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.

    Hide Tags
     Dynamic Programming String
     
        题目开始想还是挺复杂的,第一想法便是二叉树搜索,把全部可能的结果搜出来,然后如果找到了便是,找不到便不是,这样写的话速度需要考虑,提高的方法是深度查找时候判断输入的参数中字符种类个数是否一样:
    class Solution {
    public:
        bool isScramble(string s1, string s2) {
            int len1 = s1.size(),len2 = s2.size();
            if(help_f(s1,s2)){
                if(s1==s2)  return true;
                for( int i =1;i<len1;i++){
                    if(s1.substr(0,i)+s1.substr(i)==s2)    return true;
                }
                for( int i=1;i<len1;i++){
                    if(isScramble(s1.substr(0,i),s2.substr(0,i))&&isScramble(s1.substr(i),s2.substr(i)))
                        return true;
        //            cout<<s1.substr(0,i)<<" "<<s2.substr(len2-i)<<" "<<s1.substr(len1-i)<<" "<<s2.substr(0,i)<<endl;
                    if(isScramble(s1.substr(0,i),s2.substr(len2-i))&&isScramble(s1.substr(i),s2.substr(0,len2-i)))
                        return true;
                }
            }
            return false;
        }
        bool help_f(string &s1,string &s2)
        {
            if(s1.size()!=s2.size())    return false;
            int c[26]={0};
            for(int i=0;i<s1.size();i++)    c[s1[i]-'a'] ++;
            for(int i=0;i<s2.size();i++){
                c[s2[i]-'a']--;
                if(c[s2[i]-'a']<0)  return false;
            }
            return true;
        }
    };
      第二想法便是动态规划了,设table[i][j][len],i j 为字符串s1 s2 的起始位置,len 为需要考虑的长度,如果s1 的i to i + len  与 s2 的 j to j+len 符合,便为true,在长度范围内,遍历每个断开的位置,有:
     
    tab[i][j][len]  |=   tab[i][j][l] && tab[i+l][j+l][len-l]   or    tab[i][j][len]   |=  tab[i][j+len-l][l] && tab[i+l][j][len-l]
     
    class Solution
    {
    public:
        bool isScramble(string s1, string s2)
        {
            int len1=s1.size(),len2=s2.size();
            if(len1!=len2)  return false;
            bool table[100][100][100]={false};
            for(int i=len1-1;i>=0;i--){
                for(int j=len1-1;j>=0;j--){
                    table[i][j][1]=(s1[i]==s2[j]);
                    for(int tmpLen=2;i+tmpLen<=len1&&j+tmpLen<=len1;tmpLen++){
                        for(int idx=1;idx<tmpLen;idx++){
                            table[i][j][tmpLen]|=table[i][j][idx]&&table[i+idx][j+idx][tmpLen-idx];
                            table[i][j][tmpLen]|=table[i][j+tmpLen-idx][idx]&&table[i+idx][j][tmpLen-idx];
                        }
                    }
                }
            }
            return table[0][0][len1];
        }
    };
     
  • 相关阅读:
    Python 进度条
    python多线程的使用
    Python 进程间通信问题—Manager方法
    生产消费者模型(进程通信,队列)
    进程锁 购票问题
    多进程并行实现socket并发代码
    一次完整的socket文件的传输
    python实现基本计算器(可处理括号和负值)
    模拟论坛登录
    JS
  • 原文地址:https://www.cnblogs.com/Azhu/p/4239980.html
Copyright © 2020-2023  润新知