definsert(self, word): node = self.root for char in word: if char notin node.children: node.children[char] = ACNode() node = node.children[char] node.output.append(word)
defbuild_failure_pointers(self): from collections import deque queue = deque() # Initialize the first level children of root for child inself.root.children.values(): child.fail = self.root queue.append(child)
while queue: current_node = queue.popleft() for char, child in current_node.children.items(): # Find the fail pointer fail_node = current_node.fail while fail_node and char notin fail_node.children: fail_node = fail_node.fail child.fail = fail_node.children[char] if fail_node elseself.root # Merge output lists if child.fail: child.output += child.fail.output queue.append(child)
defsearch(self, text): node = self.root results = [] for index, char inenumerate(text): while node and char notin node.children: node = node.fail ifnot node: node = self.root continue node = node.children[char] if node.output: for pattern in node.output: results.append((index - len(pattern) + 1, pattern)) return results
示例用法
1 2 3 4 5 6 7 8 9 10 11 12 13
if __name__ == "__main__": patterns = ["he", "she", "his", "hers"] text = "ushers"
ac = ACAutomaton() for pattern in patterns: ac.insert(pattern) ac.build_failure_pointers() results = ac.search(text) for index, pattern in results: print(f"找到模式 '{pattern}' 在索引 {index}")