|
1 | 1 | from __future__ import annotations
|
| 2 | +from typing import Dict, List, Tuple, Union |
2 | 3 |
|
3 | 4 | END = "#"
|
4 | 5 |
|
5 |
| - |
6 | 6 | class Trie:
|
7 | 7 | def __init__(self) -> None:
|
8 |
| - self._trie: dict = {} |
| 8 | + self._trie: Dict[str, Union[Dict, bool]] = {} |
9 | 9 |
|
10 |
| - def insert_word(self, text: str) -> None: |
11 |
| - trie = self._trie |
12 |
| - for char in text: |
13 |
| - if char not in trie: |
14 |
| - trie[char] = {} |
15 |
| - trie = trie[char] |
16 |
| - trie[END] = True |
| 10 | + def insert_word(self, word: str) -> None: |
| 11 | + """Inserts a word into the trie.""" |
| 12 | + node = self._trie |
| 13 | + for char in word: |
| 14 | + if char not in node: |
| 15 | + node[char] = {} |
| 16 | + node = node[char] |
| 17 | + node[END] = True |
17 | 18 |
|
18 |
| - def find_word(self, prefix: str) -> tuple | list: |
19 |
| - trie = self._trie |
| 19 | + def find_word(self, prefix: str) -> Union[List[str], Tuple[str]]: |
| 20 | + """Finds all suffixes in the trie that match the given prefix.""" |
| 21 | + node = self._trie |
20 | 22 | for char in prefix:
|
21 |
| - if char in trie: |
22 |
| - trie = trie[char] |
| 23 | + if char in node: |
| 24 | + node = node[char] |
23 | 25 | else:
|
24 | 26 | return []
|
25 |
| - return self._elements(trie) |
| 27 | + return self._elements(node) |
26 | 28 |
|
27 |
| - def _elements(self, d: dict) -> tuple: |
| 29 | + def _elements(self, node: Dict[str, Union[Dict, bool]]) -> Tuple[str, ...]: |
| 30 | + """Recursively collects all words from the current node.""" |
28 | 31 | result = []
|
29 |
| - for c, v in d.items(): |
30 |
| - sub_result = [" "] if c == END else [(c + s) for s in self._elements(v)] |
31 |
| - result.extend(sub_result) |
| 32 | + for char, next_node in node.items(): |
| 33 | + if char == END: |
| 34 | + result.append("") |
| 35 | + else: |
| 36 | + sub_result = [char + suffix for suffix in self._elements(next_node)] |
| 37 | + result.extend(sub_result) |
32 | 38 | return tuple(result)
|
33 | 39 |
|
34 |
| - |
35 | 40 | trie = Trie()
|
36 | 41 | words = ("depart", "detergent", "daring", "dog", "deer", "deal")
|
37 | 42 | for word in words:
|
38 | 43 | trie.insert_word(word)
|
39 | 44 |
|
40 |
| - |
41 |
| -def autocomplete_using_trie(string: str) -> tuple: |
| 45 | +def autocomplete_using_trie(prefix: str) -> Tuple[str, ...]: |
42 | 46 | """
|
| 47 | + Autocompletes the given prefix using the trie. |
| 48 | +
|
43 | 49 | >>> trie = Trie()
|
44 | 50 | >>> for word in words:
|
45 | 51 | ... trie.insert_word(word)
|
46 | 52 | ...
|
47 | 53 | >>> matches = autocomplete_using_trie("de")
|
48 |
| - >>> "detergent " in matches |
| 54 | + >>> "detergent" in matches |
49 | 55 | True
|
50 |
| - >>> "dog " in matches |
| 56 | + >>> "dog" in matches |
51 | 57 | False
|
52 | 58 | """
|
53 |
| - suffixes = trie.find_word(string) |
54 |
| - return tuple(string + word for word in suffixes) |
55 |
| - |
| 59 | + suffixes = trie.find_word(prefix) |
| 60 | + return tuple(prefix + suffix for suffix in suffixes) |
56 | 61 |
|
57 | 62 | def main() -> None:
|
58 | 63 | print(autocomplete_using_trie("de"))
|
59 | 64 |
|
60 |
| - |
61 | 65 | if __name__ == "__main__":
|
62 | 66 | import doctest
|
63 |
| - |
64 | 67 | doctest.testmod()
|
65 | 68 | main()
|
0 commit comments