-
-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy path0139-word-break.py
More file actions
133 lines (115 loc) · 3.42 KB
/
0139-word-break.py
File metadata and controls
133 lines (115 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Bottom Up
# time complexity: O(n^3 +m*k)
# space complexity: O(n+m*k)
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n = len(s)
words = set(wordDict)
dp = [False for _ in range(n + 1)]
dp[0] = True
for right in range(1, n + 1):
for left in range(right):
if dp[left] and s[left: right] in words:
dp[right] = True
break
return dp[-1]
'''
l e e t c o d e
T F F F T F F F T
l
r
'''
# Tries
# time complexity: O(n^2 + m*k)
# space complexity: O(n + m*k)
from collections import deque
from typing import List
class TrieNode:
def __init__(self):
self.isWord = False
self.children = {}
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
root = TrieNode()
for word in wordDict:
curr = root
for c in word:
if c not in curr.children:
curr.children[c] = TrieNode()
curr = curr.children[c]
curr.isWord = True
dp = [False] * len(s)
for i in range(len(s)):
if i == 0 or dp[i-1]:
curr = root
for j in range(i, len(s)):
c = s[j]
if c not in curr.children:
break
curr = curr.children[c]
if curr.isWord:
dp[j] = True
return dp[-1]
# Bottom Up
# time complexity: O(n^3 +m*k)
# space complexity: O(n+m*k)
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n = len(s)
words = set(wordDict)
dp = [False] * (n + 1)
dp[0] = True
for i in range(1, n + 1):
for j in range(i):
if dp[j] and s[j:i] in words:
dp[i] = True
break
return dp[-1]
s = "leetcode"
wordDict = ["leet", "code"]
print(Solution().wordBreak(s, wordDict))
s = "applepenapple"
wordDict = ["apple", "pen"]
print(Solution().wordBreak(s, wordDict))
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
print(Solution().wordBreak(s, wordDict))
# DP 1
# time complexity: O(n*m*k)
# space complexity: O(n)
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
sLen = len(s)
dp = [False] * sLen
for i in range(sLen):
for word in wordDict:
wordLen = len(word)
if i < wordLen - 1:
continue
if i == wordLen - 1 or dp[i-wordLen]:
if s[i-wordLen+1:i + 1] == word:
dp[i] = True
break
return dp[sLen-1]
# BFS
# time complexity: O(n^3 + m*k)
# space complexity: O(n+m*k)
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
words = set(wordDict)
queue = deque([0])
seen = set()
while queue:
start = queue.popleft()
if start == len(s):
return True
for end in range(start + 1, len(s) + 1):
if end in seen:
continue
if s[start:end] in words:
queue.append(end)
seen.add(end)
return False
s = "applepenapple"
wordDict = ["apple", "pen"]
print(Solution().wordBreak(s, wordDict))