zoukankan      html  css  js  c++  java
  • AC算法--python

    # 结点类
    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、添加的词前后空格要去除

  • 相关阅读:
    控制反转和依赖注入
    共识机制是什么?
    实用拜占庭容错算法PBFT
    三种框架对比react vue 和Angular对比
    go语言学习笔记
    激活方法总结
    钱包助记词
    简历中存在的问题的处理
    why we use Symbols in Hash
    compact过滤数组中的nil
  • 原文地址:https://www.cnblogs.com/51zone/p/13224294.html
Copyright © 2011-2022 走看看