# 139. word Break
###### tags: `leetcode` `medium`
## problem
**input**
"cars"
"ccbb"
"ccaccc"
"goalspecial"
"catscatdog"
"ddadddbdddadd"
**output**
["car","ca","rs"]
["bc","cb"]
["cc","ac"]
["go","goal","goals","special"]
["cat","cats","dog"]
["dd","ad","da","b"]
## Solution
使用DP。(bottom up)
沒想到直接看答案。
f[i]代表s[:i]是可以被wordDict所組成的。
$$
f(i) =
\begin{cases}
True & \text{if $i$ = 0} \\
True, & \text{if $f(i-len(w_j))$ = True AND $w_j$ in
dict} \\
False, & \text{otherwise}
\end{cases}
$$
Time complexity:
$$
O \bigl( n^2 \bigr)
$$
Runtime | Memory Usage
--- | ---
54.17% | 5.55%
```py=
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
d = set(wordDict)
f = [False for i in range(len(s)+1)]
f[0] = True
for i in range(1, len(s)+1):
for j in range(i):
if f[j] and s[j:i] in d:
f[i] = True
break
return f[len(s)]
```
## Solution
使用暴力法
Time complexity:
$$
O \bigl( n^2 \bigr) ??
$$
Runtime | Memory Usage
--- | ---
636 ms | 15.1 MB
5.56% | 5.14%
有想法就幹,try and error
測資全過,可能有其他未知bug
## 結構一
想法1:
從字典中找到目標字串存在的詞(word),用while刪除目標字串中所有word,並以","分隔,每次刪完word,皆做判斷是否只剩最後一個詞且字典中有對應之字詞,若可即判斷True,或者將其刪到只剩","也判斷True
想法2:
字串長度有長有短,若字典將目標s刪到小於需要對應知字典詞(word)的長度,將目標s還原成刪除前的樣子i.e. s = tmp,之後再作刪除,每次刪完word,皆做判斷是否只剩最後一個詞且字典中有對應之字詞,若可即判斷True
想法3:
疊字爭議,根據經驗字典中的疊字丟到字典之後,以repeateddic分開後,到最後在刪除判斷,會正確且容易分析出字串的結構
<前三個想法組成結構一>
-----
想法4:
因為目標字是由字典所構成,目標之第一個字詞或最後一個字詞,一定也在字典之中,因此我依序刪除第一個、最後一個使原始字串(tmp)修整之後,再進行與結構(一)相同的判斷
想法5:
改變字典的刪除順序影響結果,checkIgnore 若以長度長的排前面,出現疊字丟入字典最末,若字典長度相同,將所有除疊字以外長度相同之字典字詞,進行交換,形成所有組合,並一一判斷。
若以上皆無找到字典詞組合可形成目標字串即判斷False
```py=
def wordBreak(s, wordDict):
tmp = s
splitCount = 0
repeateddic = []
checkIgnore = []
removeFromCheckIgnore = []
for word in wordDict:
if s != tmp:
checkIgnore.append(word)
'''if word.count(word[0])==len(word) and len(word)>1:
repeateddic.append(word)'''
if len(s) >= len(word)+splitCount:
if s.find(word)!=-1:
#print("replace")
#print(word)
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
elif s == tmp and s.find(word)==-1:
removeFromCheckIgnore.append(word)
else:
pass
else:
s = tmp
#print(s)
splitCount = 0
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
for word in repeateddic:
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
#print("remove")
#print(removeFromCheckIgnore)
for garbage in removeFromCheckIgnore:
if garbage in checkIgnore:
checkIgnore.remove(garbage)
while len(checkIgnore) != 0:
#print(checkIgnore)
s = tmp
splitCount = 0
for word in checkIgnore:
if len(s) >= len(word)+splitCount:
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
else:
pass
else:
s = tmp
#print(s)
splitCount = 0
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
#print(s)
#print(splitCount)
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
if len(s) == splitCount:
return True
for word in repeateddic:
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
del checkIgnore[0]
tmp2 = tmp
for r in range(len(wordDict)):
tmp = tmp2
#print("wordDict[r] = ",wordDict[r])
if tmp.find(wordDict[r])==0 or tmp.rfind(wordDict[r])==len(tmp)-len(wordDict[r]):
tmp = tmp.replace(wordDict[r],"",1)
else:
continue
s = tmp
#print("tmp = ",tmp)
splitCount = 0
repeateddic = []
checkIgnore = []
removeFromCheckIgnore = []
for word in wordDict:
if s != tmp:
checkIgnore.append(word)
if word.count(word[0])==len(word) and len(word)>1:
repeateddic.append(word)
continue
if len(s) >= len(word)+splitCount:
if s.find(word)!=-1:
#print("replace")
#print(word)
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
elif s == tmp and s.find(word)==-1:
removeFromCheckIgnore.append(word)
else:
pass
else:
s = tmp
#print(s)
splitCount = 0
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
for word in repeateddic:
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
#print("remove")
#print(removeFromCheckIgnore)
# for garbage in removeFromCheckIgnore:
# if garbage in checkIgnore:
# checkIgnore.remove(garbage)
for w in wordDict:
#print(w)
#print(not w in set(checkIgnore))
if not w in set(checkIgnore) and not w in set(repeateddic):
checkIgnore.append(w)
else:
pass
#print("remove")
#print(removeFromCheckIgnore)
for garbage in removeFromCheckIgnore:
if garbage in checkIgnore:
checkIgnore.remove(garbage)
checkIgnore_revise = [(0,0)]*len(checkIgnore)
for i in range(len(checkIgnore)):
checkIgnore_revise[i] = [len(checkIgnore[i]),i]
checkIgnore_revise.sort()
checkIgnore_2 = [""]*len(checkIgnore)
for x in range(len(checkIgnore)):
checkIgnore_2[x] = checkIgnore[checkIgnore_revise[len(checkIgnore)-1-x][1]]
#print("checkIgnore_2 = ",checkIgnore_2)
repeatedwords = 0
checkIgnore_3 = [a for a in checkIgnore_2]
for o in checkIgnore_2:
if o.count(o[0])==len(o) and len(o)>1:
checkIgnore_3.remove(o)
checkIgnore_3.append(o)
repeatedwords += 1
else:
pass
checkIgnore_4 = []
checkIgnore_4.append(checkIgnore_3)
for u in range(len(checkIgnore_3)-repeatedwords):
for v in range(1,len(checkIgnore_3)-repeatedwords):
if len(checkIgnore_3[u]) == len(checkIgnore_3[v]) and len(checkIgnore_3[u])>1 and u!=v:
#print("u,v = ",u,v )
checkIgnore_3[u],checkIgnore_3[v] = checkIgnore_3[v],checkIgnore_3[u]
#print(checkIgnore_3)
checkIgnore_5 = [q for q in checkIgnore_3]
checkIgnore_4.append(checkIgnore_5)
checkIgnore_3[u],checkIgnore_3[v] = checkIgnore_3[v],checkIgnore_3[u]
#print("checkIgnore_4=",checkIgnore_4)
for g in range(len(checkIgnore_4)):
while len(checkIgnore_4[g]) != 0:
#print(checkIgnore_4)
s = tmp
splitCount = 0
for word in checkIgnore_4[g]:
if len(s) >= len(word)+splitCount:
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
else:
pass
else:
s = tmp
#print(s)
splitCount = 0
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
for word in repeateddic:
if s.find(word)!=-1:
while s.find(word)!=-1:
s = s.replace(word,",",1)
splitCount += 1
lastelement = 2
for x in s.split(","):
if x in set(wordDict):
lastelement = 1
elif x == "":
pass
else:
lastelement = 0
break
if lastelement == 1:
return True
#print(s)
#print(splitCount)
if len(s) == splitCount:
return True
del checkIgnore_4[g][0]
return False
```