Skip to content

Commit f81d57b

Browse files
committed
feat: add solutions to lc problem: No.0139
No.0139.Word Break
1 parent e374d74 commit f81d57b

File tree

2 files changed

+380
-0
lines changed

2 files changed

+380
-0
lines changed

solution/0100-0199/0139.Word Break/README.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ $dp[i]$ 表示前 $i$ 个字符组成的字符串 $s[0...i-1]$ 能否拆分成
5858

5959
时间复杂度 $O(n^2)$。
6060

61+
**方法二:前缀树 + 记忆化搜索**
62+
63+
根据 $wordDict$ 构建前缀树 $trie$,然后枚举前缀 $s[:i]$ 作为第一个单词,若在 $trie$ 中,则递归搜索 $s[i:]$。
64+
65+
若存在满足条件的拆分方案,返回 $true$。
66+
6167
<!-- tabs:start -->
6268

6369
### **Python3**
@@ -79,6 +85,42 @@ class Solution:
7985
return dp[-1]
8086
```
8187

88+
```python
89+
class Trie:
90+
def __init__(self):
91+
self.children = [None] * 26
92+
self.is_end = False
93+
94+
def insert(self, w):
95+
node = self
96+
for c in w:
97+
idx = ord(c) - ord('a')
98+
if node.children[idx] is None:
99+
node.children[idx] = Trie()
100+
node = node.children[idx]
101+
node.is_end = True
102+
103+
def search(self, w):
104+
node = self
105+
for c in w:
106+
idx = ord(c) - ord('a')
107+
if node.children[idx] is None:
108+
return False
109+
node = node.children[idx]
110+
return node.is_end
111+
112+
class Solution:
113+
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
114+
@cache
115+
def dfs(s):
116+
return not s or any(trie.search(s[:i]) and dfs(s[i:]) for i in range(1, len(s) + 1))
117+
118+
trie = Trie()
119+
for w in wordDict:
120+
trie.insert(w)
121+
return dfs(s)
122+
```
123+
82124
### **Java**
83125

84126
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -103,6 +145,66 @@ class Solution {
103145
}
104146
```
105147

148+
```java
149+
class Trie {
150+
Trie[] children = new Trie[26];
151+
boolean isEnd;
152+
153+
void insert(String w) {
154+
Trie node = this;
155+
for (char c : w.toCharArray()) {
156+
c -= 'a';
157+
if (node.children[c] == null) {
158+
node.children[c] = new Trie();
159+
}
160+
node = node.children[c];
161+
}
162+
node.isEnd = true;
163+
}
164+
165+
boolean search(String w) {
166+
Trie node = this;
167+
for (char c : w.toCharArray()) {
168+
c -= 'a';
169+
if (node.children[c] == null) {
170+
return false;
171+
}
172+
node = node.children[c];
173+
}
174+
return node.isEnd;
175+
}
176+
}
177+
178+
class Solution {
179+
private Trie trie = new Trie();
180+
private Map<String, Boolean> memo = new HashMap<>();
181+
182+
public boolean wordBreak(String s, List<String> wordDict) {
183+
for (String w : wordDict) {
184+
trie.insert(w);
185+
}
186+
return dfs(s);
187+
}
188+
189+
private boolean dfs(String s) {
190+
if (memo.containsKey(s)) {
191+
return memo.get(s);
192+
}
193+
if ("".equals(s)) {
194+
return true;
195+
}
196+
for (int i = 1; i <= s.length(); ++i) {
197+
if (trie.search(s.substring(0, i)) && dfs(s.substring(i))) {
198+
memo.put(s, true);
199+
return true;
200+
}
201+
}
202+
memo.put(s, false);
203+
return false;
204+
}
205+
}
206+
```
207+
106208
### **C++**
107209

108210
```cpp
@@ -129,6 +231,64 @@ public:
129231
};
130232
```
131233
234+
```cpp
235+
class Trie {
236+
private:
237+
vector<Trie*> children;
238+
bool isEnd;
239+
public:
240+
Trie() : children(26), isEnd(false) {}
241+
242+
void insert(string word) {
243+
Trie* node = this;
244+
for (char c : word)
245+
{
246+
c -= 'a';
247+
if (!node->children[c]) node->children[c] = new Trie();
248+
node = node->children[c];
249+
}
250+
node->isEnd = true;
251+
}
252+
253+
bool search(string word) {
254+
Trie* node = this;
255+
for (char c : word)
256+
{
257+
c -= 'a';
258+
if (!node->children[c]) return false;
259+
node = node->children[c];
260+
}
261+
return node->isEnd;
262+
}
263+
};
264+
265+
class Solution {
266+
public:
267+
Trie* trie = new Trie();
268+
unordered_map<string, bool> memo;
269+
270+
bool wordBreak(string s, vector<string>& wordDict) {
271+
for (auto w : wordDict) trie->insert(w);
272+
return dfs(s);
273+
}
274+
275+
bool dfs(string s) {
276+
if (memo.count(s)) return memo[s];
277+
if (s == "") return true;
278+
for (int i = 1; i <= s.size(); ++i)
279+
{
280+
if (trie->search(s.substr(0, i)) && dfs(s.substr(i)))
281+
{
282+
memo[s] = true;
283+
return true;
284+
}
285+
}
286+
memo[s] = false;
287+
return false;
288+
}
289+
};
290+
```
291+
132292
### **Go**
133293

134294
```go
@@ -152,6 +312,39 @@ func wordBreak(s string, wordDict []string) bool {
152312
}
153313
```
154314

315+
```go
316+
type Trie struct {
317+
children [26]*Trie
318+
isEnd bool
319+
}
320+
321+
func newTrie() *Trie {
322+
return &Trie{}
323+
}
324+
func (this *Trie) insert(word string) {
325+
node := this
326+
for _, c := range word {
327+
c -= 'a'
328+
if node.children[c] == nil {
329+
node.children[c] = newTrie()
330+
}
331+
node = node.children[c]
332+
}
333+
node.isEnd = true
334+
}
335+
func (this *Trie) search(word string) bool {
336+
node := this
337+
for _, c := range word {
338+
c -= 'a'
339+
node = node.children[c]
340+
if !node.isEnd {
341+
return false
342+
}
343+
}
344+
return true
345+
}
346+
```
347+
155348
### **C#**
156349

157350
```cs

0 commit comments

Comments
 (0)