| 94 | self.inverse = {} |
| 95 | |
| 96 | def insert(self, word, value): |
| 97 | if not all(0 <= ord(c) < 128 for c in word): |
| 98 | raise ValueError("Use 7-bit ASCII characters only") |
| 99 | if word <= self.previous_word: |
| 100 | raise ValueError("Error: Words must be inserted in alphabetical order.") |
| 101 | if value in self.inverse: |
| 102 | raise ValueError(f"value {value} is duplicate, got it for word {self.inverse[value]} and now {word}") |
| 103 | |
| 104 | # find common prefix between word and previous word |
| 105 | common_prefix = 0 |
| 106 | for i in range(min(len(word), len(self.previous_word))): |
| 107 | if word[i] != self.previous_word[i]: |
| 108 | break |
| 109 | common_prefix += 1 |
| 110 | |
| 111 | # Check the unchecked_nodes for redundant nodes, proceeding from last |
| 112 | # one down to the common prefix size. Then truncate the list at that |
| 113 | # point. |
| 114 | self._minimize(common_prefix) |
| 115 | |
| 116 | self.data[word] = value |
| 117 | self.inverse[value] = word |
| 118 | |
| 119 | # add the suffix, starting from the correct node mid-way through the |
| 120 | # graph |
| 121 | if len(self.unchecked_nodes) == 0: |
| 122 | node = self.root |
| 123 | else: |
| 124 | node = self.unchecked_nodes[-1][2] |
| 125 | |
| 126 | for letter in word[common_prefix:]: |
| 127 | next_node = DawgNode(self) |
| 128 | node.edges[letter] = next_node |
| 129 | self.unchecked_nodes.append((node, letter, next_node)) |
| 130 | node = next_node |
| 131 | |
| 132 | node.final = True |
| 133 | self.previous_word = word |
| 134 | |
| 135 | def finish(self): |
| 136 | if not self.data: |