Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1467513

Browse files
author
杨世超
committed
更新「AC 自动机」相关内容
1 parent 3f0fa3a commit 1467513

File tree

1 file changed

+111
-2
lines changed

1 file changed

+111
-2
lines changed

‎docs/04_string/04_11_ac_automaton.md

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,119 @@ AC 自动机的构造有 3 个步骤:
1818
1919
### 2.1 构造一棵字典树(Trie)
2020

21-
首先我们需要建立一棵字典树。
21+
首先我们需要建立一棵字典树。字典树是一种树形数据结构,用于高效地存储和检索字符串集合。每个节点代表一个字符,从根节点到某个节点的路径上的字符连接起来,就是该节点对应的字符串。
22+
23+
对于给定的 5 个单词,构造的字典树如下:
24+
25+
```
26+
root
27+
/ \
28+
s h
29+
/ \ |
30+
a h e
31+
/ / \ \
32+
y e r r
33+
```
2234

2335
### 2.2 构造失配指针
2436

37+
失配指针(fail pointer)是 AC 自动机的核心。当在字典树中匹配失败时,失配指针指向另一个节点,该节点对应的字符串是当前节点对应字符串的最长后缀。
38+
39+
失配指针的构造过程:
40+
1. 根节点的失配指针指向空
41+
2. 对于每个节点,其失配指针指向其父节点的失配指针指向的节点的对应子节点
42+
3. 如果对应子节点不存在,则继续沿着失配指针向上查找
43+
2544
### 2.3 扫描文本串
2645

27-
## 3. AC 自动机的应用
46+
扫描文本串的过程:
47+
1. 从根节点开始,按照文本串的字符顺序在字典树中移动
48+
2. 如果当前字符匹配成功,继续移动到下一个字符
49+
3. 如果当前字符匹配失败,通过失配指针跳转到另一个节点继续匹配
50+
4. 当到达某个单词的结束节点时,说明找到了一个匹配的单词
51+
52+
## 3. AC 自动机的应用
53+
54+
AC 自动机在以下场景中有着广泛的应用:
55+
56+
1. **多模式字符串匹配**:在文本中查找多个模式串
57+
2. **敏感词过滤**:检测文本中是否包含敏感词
58+
3. **DNA序列分析**:在生物信息学中用于DNA序列的模式匹配
59+
4. **网络入侵检测**:检测网络数据包中的恶意模式
60+
5. **拼写检查**:检查文本中的拼写错误
61+
62+
## 4. AC 自动机的实现
63+
64+
### 4.1 时间复杂度
65+
66+
- 构建字典树:O(Σ|P|),其中 P 是所有模式串的集合
67+
- 构建失配指针:O(Σ|P|)
68+
- 文本串匹配:O(n + k),其中 n 是文本串长度,k 是匹配的模式串数量
69+
70+
### 4.2 空间复杂度
71+
72+
- O(Σ|P|),其中 Σ 是字符集大小
73+
74+
## 5. 代码实现
75+
76+
```python
77+
class TrieNode:
78+
def __init__(self):
79+
self.children = {} # 子节点
80+
self.fail = None # 失配指针
81+
self.is_end = False # 是否是单词结尾
82+
self.word = "" # 存储完整的单词
83+
84+
class AC_Automaton:
85+
def __init__(self):
86+
self.root = TrieNode()
87+
88+
def add_word(self, word):
89+
node = self.root
90+
for char in word:
91+
if char not in node.children:
92+
node.children[char] = TrieNode()
93+
node = node.children[char]
94+
node.is_end = True
95+
node.word = word
96+
97+
def build_fail_pointers(self):
98+
queue = []
99+
# 将根节点的子节点的失配指针指向根节点
100+
for char, node in self.root.children.items():
101+
node.fail = self.root
102+
queue.append(node)
103+
104+
# 广度优先搜索构建失配指针
105+
while queue:
106+
current = queue.pop(0)
107+
for char, child in current.children.items():
108+
fail = current.fail
109+
while fail and char not in fail.children:
110+
fail = fail.fail
111+
child.fail = fail.children[char] if fail else self.root
112+
queue.append(child)
113+
114+
def search(self, text):
115+
result = []
116+
current = self.root
117+
118+
for char in text:
119+
while current is not self.root and char not in current.children:
120+
current = current.fail
121+
if char in current.children:
122+
current = current.children[char]
123+
124+
# 检查当前节点是否是某个单词的结尾
125+
temp = current
126+
while temp is not self.root:
127+
if temp.is_end:
128+
result.append(temp.word)
129+
temp = temp.fail
130+
131+
return result
132+
```
133+
134+
## 6. 总结
135+
136+
AC 自动机是一种高效的多模式匹配算法,它通过结合字典树和 KMP 算法的思想,实现了在文本串中快速查找多个模式串的功能。虽然其实现相对复杂,但在需要多模式匹配的场景下,AC 自动机提供了最优的时间复杂度。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /