首页 > 其他 > 详细

Scramble String

时间:2016-06-25 17:43:16      阅读:249      评论:0      收藏:0      [点我收藏+]

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.

据说这是区间型dp的终极版本,其实难点在于如何定义状态,状态定义好了不难.首先这也是双序列问题,状态中肯定包括第一个序列的第i个,第二个序列的第j个,但是仅仅用这个不够,我们需要加上第三维即长度,最终的转换状态是dp[x][y][k],即第一个序列的x位开始,长度为k的序列和第二个序列的y位开始,长度为k的序列,是否是scramble string.

状态转换,显然像rgtae一样,我们需要找一个分割的位置,使得s2[y:y+k-1]按位置分割的这两段分别对应s1[x:x+k-1]中的两段:一共有两种对应关系,一种左边对应左边,右边对应右边,另外一种是左边对应右边,右边对应左边.如tae对应eat,或者eat对应eat.请看示意图:

技术分享

初始化,可以先检查每个字符是否对应,即dp[x][y][1].

最终结果是dp[0][0][n].代码如下:

class Solution(object):
    def isScramble(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        if len(s1) != len(s2):
            return False
        n = len(s1)
        dp = [[[False]*(n+1) for i in xrange(n)] for j in xrange(n)]
        for x in xrange(n):
            for y in xrange(n):
                if s1[x] == s2[y]:
                    dp[x][y][1] = True
        for k in xrange(2, n+1):
            for x in xrange(0, n-k+1):
                for y in xrange(0, n-k+1):
                    for i in xrange(1, k):
                        if (dp[x][y][i] and dp[x+i][y+i][k-i])  or (dp[x][y+k-i][i] and dp[x+i][y][k-i]):
                            dp[x][y][k] = True
                            break
        return dp[0][0][n]
                           

空间复杂度为O(n^3),时间复杂度为O(n^4).

这题如果不采用动态规划而是暴力递归解法.则需要枚举s1开始结束位置,s2开始结束位置,枚举s1和s2的切分位,所以复杂度为O(n^6).但是可以采取剪枝等优化方法.

有两种加速策略,一种是剪枝,提前返回;一种是加缓存,缓存中间结果,即 memorization(翻译为记忆化搜索)。具体参见leetcode-cpp题解.

Scramble String

原文:http://www.cnblogs.com/sherylwang/p/5616507.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!