Word Break
Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of dictionary words.
You are allowed to reuse words in the dictionary an unlimited number of times. You may assume all dictionary words are unique.
Example 1:
Input: s = "neetcode", wordDict = ["neet","code"]
Output: true
Explanation: Return true because "neetcode" can be split into "neet" and "code".
Example 2:
Input: s = "applepenapple", wordDict = ["apple","pen","ape"]
Output: true
Explanation: Return true because "applepenapple" can be split into "apple", "pen" and "apple". Notice that we can reuse words and also not use all the words.
Example 3:
Input: s = "catsincars", wordDict = ["cats","cat","sin","in","car"]
Output: false
Constraints:
1 <= s.length <= 200
1 <= wordDict.length <= 100
1 <= wordDict[i].length <= 20
s and wordDict[i] consist of only lowercase English letters.
Solution
To break the string, we can break it step by step. If s 0 : n s_{0:n} s0:n can be broken into words, then we just need to consider whether there exists a position m m m that s n : m s_{n:m} sn:m is a word in dictionary. So, we can record the positions that the substrings before these positions are broken, and check whether we can find a substring after these position that appears in dictionary.
One plausible way is to enumerate the next position and check the substring between two positions, whose time complexity is O ( Len 2 ( s ) ) O(\text{Len}^2(s)) O(Len2(s)). Another way is to traverse the dictionary and find one can be put after the last position, whose time complexity is O ( Len ( s ) × ∑ w Len ( w ) ) O(\text{Len}(s)\times\sum_w\text{Len}(w)) O(Len(s)×∑wLen(w))
Code
Enumerate break position:
py
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
word_set = set(wordDict)
brk = [False]*(len(s)+1)
brk[-1] = True
for i in range(len(s)):
subword = ''
for j in range(i, -1, -1):
subword = s[j]+subword
if brk[j-1] and subword in word_set:
brk[i] = True
break
print(brk)
return brk[len(s)-1]
Enumerate dictionary words:
py
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
dp = [False] * (len(s) + 1)
dp[len(s)] = True
for i in range(len(s) - 1, -1, -1):
for w in wordDict:
if (i + len(w)) <= len(s) and s[i : i + len(w)] == w:
dp[i] = dp[i + len(w)]
if dp[i]:
break
return dp[0]