|
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