-
Notifications
You must be signed in to change notification settings - Fork 0
/
TrieTree.py
252 lines (203 loc) · 5.96 KB
/
TrieTree.py
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
"""
字典树相关题目:
LeetCode208 实现前缀树
LeetCode648 单词替换
LeetCode211 添加与搜索单词
LeetCode677 键值映射
"""
import collections
from collections import deque
# TrieSet LeetCode208 实现前缀树
# 只需要判断是否是结尾,不需要存储value
# TrieNode 写法
class TrieNode:
def __init__(self):
self.children = collections.defaultdict(TrieNode)
self.isEnd = None
class Trie:
def __init__(self):
self.root = TrieNode()
@staticmethod
def insert(self, word):
node = self.root
for c in word:
node = node.children[c]
node.isEnd = True
def search(self, word):
node = self.root
for c in word:
node = node.children.get(c)
if node is None:
return False
return node.isEnd
def startswith(self, prefix):
node = self.root
for c in prefix:
node = node.children.get(c)
if node is None:
return False
return True
# 字典写法
class TrieDic:
def __init__(self):
self.root = {}
def insert(self, word):
node = self.root
for c in word:
if c not in node:
node[c] = {}
node = node[c]
node['#'] = {}
def search(self, word):
node = self.root
for c in word:
if c not in node:
return False
node = node[c]
return True
def startswith(self, prefix):
node = self.root
for c in prefix:
if c not in node:
return False
node = node[c]
return True
# LeetCode648 单词替换
# TrieNode写法
class Trie1(Trie):
def __init__(self):
super().__init__()
self.root = TrieNode()
self.isEnd = False
def insert(self, word):
node = self.root
for c in word:
node = node.children[c]
node.isEnd = True
def shortestPrefix(self, prefix):
node = self.root
for i in range(len(prefix)):
if node is None:
return ""
if node.isEnd:
return prefix[i]
node = node.children[prefix[i]]
if node and node.isEnd:
return prefix
return ""
class Solution:
def replaceWords(self, dictionary: list[str], sentence: str) -> str:
trie = Trie1()
for d in dictionary:
trie.insert(d)
words = sentence.split(' ')
for i in range(len(words)):
prefix = trie.shortestPrefix(words[i])
if prefix:
words[i] = prefix
return ' '.join(words)
# 字典写法
class TrieDic1:
def __init__(self):
self.root = {}
def insert(self, word):
node = self.root
for c in word:
if c not in node:
node[c] = {}
node = node[c]
node['#'] ={}
def find_sp(self, word):
node = self.root
for i in range(len(word)):
if '#' in node:
return word[:i]
if word[i] in node:
node = node[word[i]]
else:
break
return word
class Solution:
def replaceWords(self, dictionary: list[str], sentence: str) -> str:
trie = TrieDic1()
for dic in dictionary:
trie.insert(dic)
words = sentence.split(' ')
return ' '.join(trie.find_sp(word) for word in words)
# LeetCode 211 添加与搜索单词
# TrieNode 方法
class WordDictionary:
def __init__(self):
self.root = TrieNode()
def addWord(self, word: str) -> None:
node = self.root
for c in word:
node = node.children[c]
node.isEnd = True
def search(self, word: str) -> bool:
return self.match(word, 0, self.root)
def match(self, word, idx, root):
if not root:
return False
if idx == len(word):
return root.isEnd
if word[idx] != '.':
return self.match(word, idx + 1, root.children.get[word[idx]])
else:
for child in root.children.values():
if self.match(word, idx + 1, child.child):
return True
return False
# 字典方法
class WordDictionary:
def __init__(self):
self.root = {}
def addWord(self, word: str) -> None:
node = self.root
for c in word:
if c not in node:
node[c] = {}
node = node[c]
node['#'] = {}
def search(self, word: str) -> bool:
word += '#'
bfs = deque([(0, self.root)])
while bfs:
idx, cur = bfs.popleft()
if idx == len(word):
return True
if word[idx] == '.':
for nxt in cur.values():
bfs.append((idx + 1, nxt))
elif word[idx] in cur:
bfs.append((idx + 1, cur[word[idx]]))
return False
# 677 键值映射
# 字典方法
class MapSum:
def __init__(self):
self.root = {}
def insert(self, key: str, val: int) -> None:
node = self.root
for c in key:
if c not in node:
node[c] = {}
node = node[c]
node['val'] = val
def sum(self, prefix: str) -> int:
node = self.root
for c in prefix:
if c not in node:
return 0
else:
node = node[c]
ans = 0
def dfs(node):
for c in node:
if c == 'val':
nonlocal ans
ans += node[c]
else:
dfs(node[c])
dfs(node)
return ans