Golang AC自动机算法实现
最近在学习AC自动机算法,想用Golang实现一个高效的多模式字符串匹配工具。但有几个问题不太明白:
- Golang中如何设计Trie树结构比较合适?用struct还是map实现节点更好?
- 构建失败指针时,用BFS遍历的话,Golang的队列用什么数据结构实现性能最好?
- 对于大规模模式串(比如上万个关键词),有什么优化内存的技巧吗?
- 能否分享一个完整的Golang实现示例?最好能包含匹配过程和性能测试部分。
希望有实际项目经验的大佬能指点一下,谢谢!
2 回复
Golang中AC自动机可通过Trie树和失败指针实现。使用map[rune]*node存储子节点,fail指针处理匹配失败跳转。构建Trie后通过BFS建立fail指针,最后扫描文本时利用fail指针实现多模式匹配。代码约100行,适合敏感词过滤等场景。
更多关于Golang AC自动机算法实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
AC自动机(Aho-Corasick Algorithm)是一种多模式匹配算法,用于在文本中同时查找多个关键词。以下是Golang的实现步骤和代码示例:
核心步骤
- 构建Trie树:插入所有模式串。
- 添加失败指针:通过BFS为每个节点设置失败指针,指向最长真后缀对应的节点。
- 匹配过程:遍历文本,利用失败指针跳转,高效匹配所有模式。
代码实现
package main
import (
"fmt"
)
type Node struct {
children map[rune]*Node // 子节点
fail *Node // 失败指针
output []string // 匹配的模式串(结束节点存储)
}
func NewNode() *Node {
return &Node{
children: make(map[rune]*Node),
output: make([]string, 0),
}
}
type AhoCorasick struct {
root *Node
}
func NewAhoCorasick() *AhoCorasick {
return &AhoCorasick{root: NewNode()}
}
// 插入模式串
func (ac *AhoCorasick) Insert(pattern string) {
node := ac.root
for _, ch := range pattern {
if node.children[ch] == nil {
node.children[ch] = NewNode()
}
node = node.children[ch]
}
node.output = append(node.output, pattern)
}
// 构建失败指针
func (ac *AhoCorasick) Build() {
queue := []*Node{}
// 根节点的子节点失败指针指向根
for _, child := range ac.root.children {
child.fail = ac.root
queue = append(queue, child)
}
// BFS设置失败指针
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
for ch, child := range current.children {
queue = append(queue, child)
// 从当前节点的失败指针开始查找
failNode := current.fail
for failNode != nil && failNode.children[ch] == nil {
failNode = failNode.fail
}
if failNode == nil {
child.fail = ac.root
} else {
child.fail = failNode.children[ch]
// 合并输出(后缀匹配的模式)
child.output = append(child.output, child.fail.output...)
}
}
}
}
// 匹配文本
func (ac *AhoCorasick) Search(text string) map[string][]int {
result := make(map[string][]int)
node := ac.root
for i, ch := range text {
// 跳转失败指针直到匹配或到根
for node != ac.root && node.children[ch] == nil {
node = node.fail
}
if nextNode, exists := node.children[ch]; exists {
node = nextNode
} else {
node = ac.root
}
// 记录匹配结果
for _, pattern := range node.output {
startPos := i - len(pattern) + 1
result[pattern] = append(result[pattern], startPos)
}
}
return result
}
// 示例使用
func main() {
ac := NewAhoCorasick()
patterns := []string{"he", "she", "his", "hers"}
for _, p := range patterns {
ac.Insert(p)
}
ac.Build()
text := "ushers"
matches := ac.Search(text)
for pattern, positions := range matches {
fmt.Printf("模式 '%s' 出现在位置: %v\n", pattern, positions)
}
}
输出示例
模式 'he' 出现在位置: [1 3]
模式 'she' 出现在位置: [2]
模式 'hers' 出现在位置: [2]
关键点
- 时间复杂度:构建O(总模式长度),匹配O(文本长度+匹配数)。
- 空间优化:使用
map[rune]*Node动态存储子节点,适合字符集大的场景。 - 应用场景:敏感词过滤、基因序列分析等。
此实现完整覆盖AC自动机的核心逻辑,可直接用于多模式匹配任务。

