###### tags: `Leetcode` `medium` `dynamic programming` `python` # 97. Interleaving String ## [題目連結:] https://leetcode.com/problems/interleaving-string/ ## 題目: Given strings ```s1, s2, and s3```, find whether ```s3``` is formed by an **interleaving** of ```s1 and s2```. An interleaving of two strings s and t is a configuration where s and t are divided into n and m non-empty substrings respectively, such that: * s = s1 + s2 + ... + sn * t = t1 + t2 + ... + tm * |n - m| <= 1 * The **interleaving** is s1 + t1 + s2 + t2 + s3 + t3 + ... or t1 + s1 + t2 + s2 + t3 + s3 + ... **Note**: ```a + b``` is the concatenation of strings ```a``` and ```b```. ## 解題想法: * 給三個string s1,s2,s3: 判斷s3是否可由s1,s2交錯組合而成 * s1、s2之原本組成之順序不能變 * 即s1 = 'abc',在使用時候,'a'一定要在'bc'前 * 使用dp: * 定義dp[i][j]為:使用s1[:i]之string與s2[:j]之string,是否能交錯合併為s3[:i+j-1] * 起始判斷: * l1 = len(s1) * l2 = len(s2) * l3 = len(s3 * 若總長度l3!=l1+l2,return False * init: * dp = [[0 for _ in range(l2+1)] for _ in range(l1+1)] * dp[0][0]=True * s1不取任何字,s2不取任何字,能合成不取任何字的s3,所以為True * 初始化第一行(左邊界) * 意義為判斷s1中哪些位置的字元,對於在s3中相同位置,兩者字元相等 * 還需考慮上個位置使否為True,因為字元原本組成之順序不能變 * for i in range(1,l1+1): dp[i][0] = dp[i-1][0] and (s1[i-1]==s3[i-1]) * 初始化第一列(上邊界) * 意義為判斷s2中哪些位置的字元,對於在s3中相同位置,兩者字元相等 * 還需考慮上個位置使否為True,因為字元原本組成之順序不能變 * for j in range(1,l2+1): dp[0][j] = dp[0][j-1] and (s2[j-1]==s3[j-1]) * 對於dp[i][j]: * 考慮其 左方dp[i][j-1]與 上方dp[i-1][j] * 若其中一者為True: * if 左方s1為True:(dp[i][j-1]==True) * 需再考慮 (其s2: 目前值s2[j-1]是否等於s3[i+j-1]) * if 上方s2為True:(dp[i-1][j]==True) * 需再考慮 (其s1: 目前值s1[i-1]是否等於s3[i+j-1]) * 需判斷是否等於s3[i+j-1]原因為:因為總體長度須保持len(s1[:x])+len(s2[:y])=len(s3[:x+y-1]) * 示意dp數組 ``` s1 = "aabcc" s2 = "dbbca" s3 = "aadbbcbcac" s2 Ø d b b c a s1 Ø T F F F F F a T F F F F F a T T T T T F b F T T F T F c F F T T T T c F F F T F 'T' ans = True ``` ## Python: ``` python= class Solution(object): def isInterleave(self, s1, s2, s3): """ :type s1: str :type s2: str :type s3: str :rtype: bool """ #判斷 l1 = len(s1) l2 = len(s2) l3 = len(s3) if (l1+l2)!=l3: return False #init dp = [[0 for _ in range(l2+1)] for _ in range(l1+1)] dp[0][0]=True #初始化上下邊 for i in range(1,l1+1): dp[i][0] = dp[i-1][0] and (s1[i-1]==s3[i-1]) #初始化左右邊 for j in range(1,l2+1): dp[0][j] = dp[0][j-1] and (s2[j-1]==s3[j-1]) #Dp for i in range(1,l1+1): for j in range(1,l2+1): dp[i][j] = (dp[i-1][j]==True and s1[i-1]==s3[i-1+j])or(dp[i][j-1]==True and s2[j-1]==s3[j-1+i]) return dp[l1][l2] result = Solution() s1 = "aabcc" s2 = "dbbca" s3 = "aadbbcbcac" ans = result.isInterleave(s1,s2,s3) print(ans) ```