Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
solutions
recursion w/ memoization
At each recursive step, choose to split the string at idx, or continue accumulating a string.
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
word_set = set(wordDict)
memo = {}
def recurse(idx, wl):
if idx == len(s) and wl == len(s):
return True
if idx == len(s) or wl == len(s):
return False
if (idx, wl) in memo:
return memo[(idx, wl)]
# if wl to idx forms word in list,
# choose to either split with it or not
splittable = False
window_word = s[wl:idx+1]
# choose to split here, start next
# word in recursion
if window_word in word_set:
splittable = splittable or recurse(idx+1, idx+1)
# don't split here, continue to next index
splittable = splittable or recurse(idx+1, wl)
memo[(idx, wl)] = splittable
return splittable
return recurse(0, 0)dp
Instead of top-down recursion, we can build the solution bottom-up by starting with the empty string, and adding characters. For any given string ending at , we look back at all prior indices where the string was splittable, and see if the string s[j:i+1] is valid.
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
word_set = set(wordDict)
dp = [True]
for i in range(len(s)):
j = i
dp.append(False)
while j >= 0:
if dp[j] and s[j:i+1] in word_set:
dp[-1] = True
break
j -= 1
return dp[-1]