87.扰乱字符串
class Solution: def isScramble(self, s1: str, s2: str) -> bool: # DP 难点分析: # 1.首先理解三层DP分别代表:长度,s1起点,s2起点 # 2.初始化DP长度为1的DP子串 # 3.状态转移方程,长度为l的dp[l]可以从dp[l-k] 与 dp[k] 转移而来 # 4.DP种几层端点的选择 # 1) 对于len是有实际意义的,不能为0,并且初始化时遍历了1,所以其取值为 range(2,lens+1) # 2) 对于端点都是从index = 0开始的,但是要保证index+l <=lens; # 比如 lens = 10, l = 8(包括i的8个数) ,i = 0,1,2 = range(lens-l+1) # 3) 对于分隔符号k,取值范围为 1,l-1 因为 = range(1,l) if sorted(s1)!=sorted(s2): return False if s1==s2: return True lens = len(s1) dp = [[[False]*(lens) for _ in range(lens)]for _a in range(lens+1)] for i in range(lens): for j in range(lens): dp[1][i][j] = s1[i] == s2[j] for l in range(2,lens+1): for i in range(lens-l+1): for j in range(lens-l+1): for k in range(1,l+1): # 如果 l = 8, k = 2 # 没有扰乱 s1 = i:i+2 ,i+2,i+8 # s2 = j:j+k, j+k:j+l if dp[k][i][j] and dp[l-k][i+k][j+k]: dp[l][i][j] = True break # 扰乱 s2 = j+l-k:j+l , j:j+l-k if dp[k][i][j+l-k] and dp[l-k][i+k][j]: dp[l][i][j] = True break return dp[lens][0][0] # 递归, # basecase: 两字符串相等 返回true # 上层: 对于每一个切分点,如果对应段相等,或者交叉相等,则返回True # if sorted(s1) != sorted(s2):return False # if s1 == s2 :return True # for i in range(1,len(s1)): # s11,s12 = s1[:i],s1[i:] # # 正向切s2 比如长度为8 i=1分成1,7 # s21,s22 = s2[:i],s2[i:] # if self.isScramble(s11,s21) and self.isScramble(s12,s22): # return True # # 反向切s2 比如长度为8 i=1分成7,1 # s21,s22 = s2[:len(s1)-i],s2[len(s1)-i:] # if self.isScramble(s11,s22) and self.isScramble(s12,s21): # return True # return False
class Solution:
def isScramble(self, s1: str, s2: str) -> bool:
# DP 难点分析:
# 1.首先理解三层DP分别代表:长度,s1起点,s2起点
# 2.初始化DP长度为1的DP子串
# 3.状态转移方程,长度为l的dp[l]可以从dp[l-k] 与 dp[k] 转移而来
# 4.DP种几层端点的选择
# 1) 对于len是有实际意义的,不能为0,并且初始化时遍历了1,所以其取值为 range(2,lens+1)
# 2) 对于端点都是从index = 0开始的,但是要保证index+l <=lens;
# 比如 lens = 10, l = 8(包括i的8个数) ,i = 0,1,2 = range(lens-l+1)
# 3) 对于分隔符号k,取值范围为 1,l-1 因为 = range(1,l)
if sorted(s1)!=sorted(s2):
return False
if s1==s2:
return True
lens = len(s1)
dp = [[[False]*(lens) for _ in range(lens)]for _a in range(lens+1)]
for i in range(lens):
for j in range(lens):
dp[1][i][j] = s1[i] == s2[j]
for l in range(2,lens+1):
for i in range(lens-l+1):
for j in range(lens-l+1):
for k in range(1,l+1):
# 如果 l = 8, k = 2
# 没有扰乱 s1 = i:i+2 ,i+2,i+8
# s2 = j:j+k, j+k:j+l
if dp[k][i][j] and dp[l-k][i+k][j+k]:
dp[l][i][j] = True
break
# 扰乱 s2 = j+l-k:j+l , j:j+l-k
if dp[k][i][j+l-k] and dp[l-k][i+k][j]:
dp[l][i][j] = True
break
return dp[lens][0][0]
# 递归,
# basecase: 两字符串相等 返回true
# 上层: 对于每一个切分点,如果对应段相等,或者交叉相等,则返回True
# if sorted(s1) != sorted(s2):return False
# if s1 == s2 :return True
# for i in range(1,len(s1)):
# s11,s12 = s1[:i],s1[i:]
# # 正向切s2 比如长度为8 i=1分成1,7
# s21,s22 = s2[:i],s2[i:]
# if self.isScramble(s11,s21) and self.isScramble(s12,s22):
# return True
# # 反向切s2 比如长度为8 i=1分成7,1
# s21,s22 = s2[:len(s1)-i],s2[len(s1)-i:]
# if self.isScramble(s11,s22) and self.isScramble(s12,s21):
# return True
# return False