您的位置:首页 > 编程语言 > Go语言

[题解][LeetCode][Scramble String]

2014-07-30 14:47 351 查看
题目:

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 boolean
def isScramble(self, s1, s2):
if len(s1) != len(s2):
return False
n = len(s1)
if n == 0:
return True
a = set(s1)
b = set(s2)
if a != b:
return False

t3=[[[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:
continue
for 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]:
break

return t3
[0][0]


参考:
http://blog.csdn.net/fightforyourdream/article/details/17707187 http://www.blogjava.net/sandy/archive/2013/05/22/399605.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Algorithm LeetCode