[题解][LeetCode][Scramble String]

来源:互联网 发布:购买淘宝网店铺 编辑:程序博客网 时间:2024/05/01 01:11

题目:

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.


题解:

三维动态规划+剪枝优化

思路是,若两个string互为scrambled,那么一定能找到一个分割点,s1左与s2左为scrambled,s1右和s2右为scrambled。

因为可以左右交换,所以也可能是 s1左 与 s2右 为scrambled,s1右 和 s2左 为scrambled。


所以我们要做的就是枚举这个分界点。

可选的办法是递归,也可以用动态规划来做。

设t3[k][i][j],True表示两个子串互为scrambled。三维分别意为,k是子串的长度,i是s1子串的起点,j是s2子串的起点。

即,两个子串分别为,i...i+k-1, j...j+k-1


依次枚举k, i, j, 以及分界点h

for k in range(2,n+1) :for i in range(n-k+1)[::-1] :for j in range(n-k+1)[::-1] :for h in range(1,k) :


LeetCode上面时间限制的比较厉害。若是要AC,还需要两个剪枝:

1. 如果两个子串连所含的字母都不一样,那么continue,跳过,枚举下一个子串。

2. 如果已经找到当前两个子串一个正确的划分点,那么break,跳过剩下的枚举


Code:

class Solution:# @return a booleandef isScramble(self, s1, s2):if len(s1) != len(s2):return Falsen = len(s1)if n == 0:return Truea = set(s1)b = set(s2)if a != b:return Falset3=[[[False for i in range(n+1)] for i in range(n+1)]for i in range(n+1)]for i in range(n):for j in range(n):t3[1][i][j] = s1[i] is s2[j]for k in range(2,n+1) :for i in range(n-k+1)[::-1] :l1 = list(s1[i:i+k])l1.sort()for j in range(n-k+1)[::-1] :l2 = list(s2[j:j+k])l2.sort()if l1 != l2:continuefor h in range(1,k) :t3[k][i][j] = t3[k][i][j] or (t3[h][i][j] and t3[k-h][i+h][j+h]) or (t3[h][i][j+k-h] and t3[k-h][i+h][j])if t3[k][i][j]: breakreturn t3[n][0][0]


参考:

http://blog.csdn.net/fightforyourdream/article/details/17707187

http://www.blogjava.net/sandy/archive/2013/05/22/399605.html

0 0