码迷,mamicode.com
首页 > 其他好文 > 详细

Scramble String

时间:2019-12-21 22:56:17      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:build   c++   produce   can   bool   code   represent   相同   get   

Description

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.

You can start scrambling from any binary tree legally built from s1, but you can not rebuild another binary tree while you are scrambling to get s2.

 

Example

Example 1:

Input: s1 = "great", s2 = "rgeat"
Output: true
Explanation: As described above.

Example 2:

Input: s1 = "a", s2 = "b"
Output: false

Challenge

O(n3) time

 

思路:

如果组成 s1 和 s2 的每种字符的数量不同, 可以直接判定为 false, 例如样例2的 "a" 和 "b". 以及两个字符串长度不相同也可以直接返回 false.

这道题目的重点实际上是找到构造二叉树的方式. 二叉树的构造决定了 s1 的哪些部分可以交换位置来得到新的字符串. 下面提供了多个版本算法的代码, 这里只介绍动态规划的思路:

设定状态: f[l1][r1][l2][r2] 表示是否可以由 s1 的[l1, r1]的子串攀爬得到 s2 的[l2, r2]的子串. 决策便是从哪里分割 s1, 所以我们枚举分割的点, 于是达到了子问题.

不过需要注意的是, 由于二叉树的子节点可以被交换, 所以 s2 可能是被交换过的, 所以完整的状态转移方程是:

// 枚举k, 表示从 s1的 [l1, r1] 的第k个字符后分割, 只要有其中一种分割可以得到 s2 即可, 因此是在枚举的 k 中取 或运算
f[l1][r1][l2][r2] = OR (f[l1][l1 + k - 1][l2][l2 + k - 1] && f[l1 + k][r1][l2 + k][r2]) // 该节点的两个子节点没有交换过
                    OR (f[l1][l1 + k - 1][r2 - k + 1][r2] && f[l1 + k][r1][l2][r2 - k]) // 该节点的两个子节点交换过

边界状态即: f[l1][l1][l2][l2] = (s1[l1] == s2[l2])

注意到 r1 - l1 == r2 - l2, 所以这个四维数组可以被优化掉一维.

public class Solution {
    /**
     * @param s1: A string
     * @param s2: Another string
     * @return: whether s2 is a scrambled string of s1
     */
    HashMap<String, Boolean> hash = new HashMap<String, Boolean>();

    public boolean isScramble(String s1, String s2) {
        // Write your code here
        if (s1.length() != s2.length())
            return false;

        if (hash.containsKey(s1 + "#" + s2))
            return hash.get(s1 + "#" + s2);

        int n = s1.length();
        if (n == 1) {
            return s1.charAt(0) == s2.charAt(0);
        }
        for (int k = 1; k < n; ++k) {
            if (isScramble(s1.substring(0, k), s2.substring(0, k)) && isScramble(s1.substring(k, n), s2.substring(k, n))
                    || isScramble(s1.substring(0, k), s2.substring(n - k, n))
                            && isScramble(s1.substring(k, n), s2.substring(0, n - k))) {
                hash.put(s1 + "#" + s2, true);
                return true;
            }
        }
        hash.put(s1 + "#" + s2, false);
        return false;
    }
}

  

 

 

Scramble String

标签:build   c++   produce   can   bool   code   represent   相同   get   

原文地址:https://www.cnblogs.com/FLAGyuri/p/12078279.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!