介绍:
Aho Corasick算法,简单的说就是用来在一个“大字符串”中查找精确匹配的某些“小字符串”的,发明者是Alfred V. Aho和Margaret J. Corasick。(向两位前辈致敬,orz)
这个算法的牛逼之处在于,只需要一次遍历便可以找出所有匹配的“小字符串”,因此算法复杂度为O(n+m+z)。而一个普通的匹配算法可能需要O(n+km)。
n = 所有“小字符串”的累计长度
m = “大字符串”长度
z = "小字符串"在"大字符串"里累计出现的次数
k = "小字符串"的个数
更多关于Aho Corasick算法,这里的一个课件讲得非常清楚: http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
大家也可以去wikipedia: http://en.wikipedia.org/wiki/Aho-Corasick_algorithm.
伪码:
//g(q,a)返回值为:从当前状态q接受输入字符a后应转入的下一个状态
//f(q)返回值为:在当前状态q接受无法匹配的字符后应转入的下一个状态 (当有多个候选状态时,就看谁的路径能匹配当前状态的路径的尽可能长的后缀)
//out(q)返回值为:当前状态可以输出的匹配的“小字符串”(注意,可以是多个)
q := 0; // initial state (root)
for i := 1 to m do
while g(q, T[i]) = null do
q := f(q); // follow a fail
q := g(q, T[i]); // follow a goto
if out(q) != null; then print i, out(q);
end for;
例子:
这里给出的例子的数据为:
小字符串: {a, ab, bc, bca, c, caa}
大字符串: abccab
附有“小字符串”库生成的自动机图:
(图片质量比较糙,因为是用windows画图程序手工画的,请见谅。)
(图中带有字符的箭头对应g(q,a),不带字符的箭头对应f(q),节点旁边的括号内字符为输出)
C++代码: