ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

AC算法--python

2020-07-02 14:05:24  阅读:236  来源: 互联网

标签:结点 ch temp python self AC 算法 child root


# 结点类
class node:
    def __init__(self, ch):
        self.ch = ch  # 结点值
        self.fail = None  # Fail指针
        self.tail = 0  # 尾标志:标志为 i 表示第 i 个模式串串尾
        self.child = []  # 子结点
        self.childvalue = []  # 子结点的值


# AC自动机类
class acmation:
    def __init__(self):
        self.root = node("r")  # 初始化根结点
        self.count = 0  # 模式串个数

    # 第一步:模式串建树
    def insert(self, strkey):
        self.count += 1  # 插入模式串,模式串数量加一
        p = self.root
        for i in strkey:
            if i not in p.childvalue:  # 若字符不存在,添加子结点
                child = node(i)
                p.child.append(child)
                p.childvalue.append(i)
                p = child
            else:  # 否则,转到子结点
                p = p.child[p.childvalue.index(i)]
        p.tail = self.count  # 修改尾标志

    # 第二步:修改Fail指针
    def ac_automation(self):
        queuelist = [self.root]  # 用列表代替队列
        while len(queuelist):  # BFS遍历字典树
            temp = queuelist[0]
            queuelist.remove(temp)  # 取出队首元素
            for i in temp.child:
                if temp == self.root:  # 根的子结点Fail指向根自己
                    i.fail = self.root
                else:
                    p = temp.fail  # 转到Fail指针
                    while p:
                        if i.ch in p.childvalue:  # 若结点值在该结点的子结点中,则将Fail指向该结点的对应子结点
                            i.fail = p.child[p.childvalue.index(i.ch)]
                            break
                        p = p.fail  # 否则,转到Fail指针继续回溯
                    if not p:  # 若p==None,表示当前结点值在之前都没出现过,则其Fail指向根结点
                        i.fail = self.root
                queuelist.append(i)  # 将当前结点的所有子结点加到队列中

    # 第三步:模式匹配
    def runkmp(self, strmode):
        p = self.root
        cnt = {}  # 使用字典记录成功匹配的状态
        for i in strmode:  # 遍历目标串
            # print(i,p.ch)
            while i not in p.childvalue and p is not self.root:
                p = p.fail
            if i in p.childvalue:  # 若找到匹配成功的字符结点,则指向那个结点,否则指向根结点
                p = p.child[p.childvalue.index(i)]
            else:
                p = self.root
            temp = p
            # print(i, p.ch, temp.ch)
            while temp is not self.root:
                if temp.tail:  # 尾标志为0不处理
                    if temp.tail not in cnt:
                        cnt.setdefault(temp.tail)
                        cnt[temp.tail] = 1
                    else:
                        cnt[temp.tail] += 1
                temp = temp.fail
            # print(i, p.ch, temp.ch)
        return cnt  # 返回匹配状态
        # 如果只需要知道是否匹配成功,则return bool(cnt)即可
        # 如果需要知道成功匹配的模式串种数,则return len(cnt)即可
# key = ["bc","abc" ]  # 创建模式串
# acp = acmation()
#
# for i in key:
#     acp.insert(i)  # 添加模式串
#
# acp.ac_automation()
#
# text = 'abcxbcxdbc'
# print(text)
# d = acp.runkmp(text)  # 运行自动机
# print(d)  # 打印
# {2: 1, 1: 3}
# for i in d.keys():
#     print(key[i - 1], d[i])  # 将子串匹配的数量显示
#
# abc 1
# bc 3
# exit()

注意问题:
1、添加的词前后空格要去除

标签:结点,ch,temp,python,self,AC,算法,child,root
来源: https://www.cnblogs.com/51zone/p/13224294.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有