今天需要使用AC 自动机优化下程序,想从网上找现成的代码拿来直接用,然而在网上找到的代码都不对!!!也许是我的检索能力差吧!!!
好吧,我自己学习着写吧!
这里写链接内容
上面链接的讲解很好,读完之后就明白AC自动机了。但是作者提供的代码有错误,因而,根据文章的思路,写了基于Python的实现算法。
# -*- coding: utf-8 -*-
# @Time : 7/5/2018 5:27 PM
# @Author : saintfe
# @File : ac_automation.py
def main():
l = ['hert', 'this', 'ishe', 'hit','it']
ac = AC(l)
# ac.temp()
res = ac.search("ithisherti")
print(res)
l = ['hers','his','he', 'she', 'zshe']
ac = AC(l)
res = ac.search('hiszshershe')
print(res)
class AC(object):
''''''
def __init__(self, word_list):
self.root = Node('', 0)
for word in word_list:
self.add(word)
self.make_fail()
def add(self, word):
node = self.root
for idx, char in enumerate(word):
idx += 1
node = node.transfer.setdefault(char, Node(char, idx, node))
node.output.append(word)
def make_transfer(self, node, char):
if char in node.transfer.keys():
return node.transfer[char]
elif node.level == 0:# root node
return node # 遍历到根,返回根
else:
return self.make_transfer(self.find_fail(node), char)
def find_parent(self, node):
if node.parent:
return node.parent
return self.root
def find_fail(self, node):
if node.level == 0:
return node
return node.fail
def make_fail(self):
queue = [self.root]
while queue:
node = queue.pop(0)
queue.extend(node.transfer.values())
if self.find_parent(node).level == 0:
node.fail = self.root
else:
node.fail = self.make_transfer( self.find_fail( self.find_parent(node) ), node.char )
node.output.extend(node.fail.output) # 大胆些,没有重复
def search(self, word):
res = []
node = self.root
for char in word:
node = self.make_transfer(node, char)
if node.output:
res.extend(node.output)
return res
class Node(object):
''''''
def __init__(self,char, level , node = None):
self.char = char
self.parent = node
self.level = level
self.transfer = {} # 转移函数
self.fail = None
self.output = []
if __name__ == '__main__':
main()