Question
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.
Note:
- The same word in the dictionary may be reused multiple times in the segmentation.
- You may assume the dictionary does not contain duplicate words.
Example 1:
Input:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
Output:
[
"cats and dog",
"cat sand dog"
]
Example 2:
Input:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
Output:
[
"pine apple pen apple",
"pineapple pen apple",
"pine applepen apple"
]
Explanation: Note that you are allowed to reuse a dictionary word.
Example 3:
Input:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
Output:
[]
Solution 1: Backtracking
Worst case time complexity is \(O(n^n)\), so it is TLE.
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: List[str]
"""
res = list()
self.backtracking(s, wordDict, len(s), res, [], 0)
return res
def backtracking(self, s, wordDict, length, res, partial, index):
if index == length:
res.append(' '.join(partial))
else:
for end in range(index + 1, length + 1):
if s[index: end] in wordDict:
self.backtracking(s, wordDict, length, res, partial + [s[index: end]], end)
Solution 2: DP
\(O(n^3)\) complexity. It is prone to TLE if the string is long but not breakable.
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: List[str]
"""
if len(s) == 0 or len(wordDict) == 0:
return []
if not self.wordBreak1(s, wordDict):
return []
dp = list()
dp.append([])
wordDict = set(wordDict)
max_len = max([len(word) for word in wordDict])
for i in range(1, len(s) + 1):
res = list()
for j in range(i - 1, max(-1, i - max_len - 1), -1):
if s[j:i] in wordDict:
if j == 0:
res.append(s[j:i])
elif len(dp[j]) != 0:
for partial in dp[j]:
res.append("{} {}".format(partial, s[j:i]))
dp.append(res)
return dp[-1]