AC自动机

简介: KMP 的思想:对 Trie 树上所有的结点构造失配指针。

image.png


昨天写了前缀树,今天就来看看它的一个应用吧——AC自动机


AC自动机作用:


一篇大文章 str,一个包含若干敏感词的词典 str[],收集文章中所有出现的敏感词


实现:


建立一个 AC 自动机有两个步骤:


  1. 基础的 Trie 结构:将所有的模式串构成一棵 Trie。
  2. KMP 的思想:对 Trie 树上所有的结点构造失配指针。


image.png


而铅笔部分就是失配指针fail,每个节点都有适配指针,没画的fail指针的节点都是指向root的,通过它就实现了KMP的效果(匹配到后面匹配不上了也能尽量利用前面匹配上的部分)


接下来废话少说,上代码,相信配合注释和上一文的前缀树基础你应该能很容易的看懂什么下面的代码了,如果还没看前缀树,那点这前缀树


class ACAutomation {
    static class Node {
        // end 用于一个字符串的末尾节点存放当前字符串
        // 路上经过的节点的 end 都是为 null 的
        private String end;
        private boolean endUse; // 用于记录是否已经收集过该字符串了
        private Node fail;  // 失配指针
        private Node[] nexts = new Node[26];
    }
    Node root = new Node();
    // 插入敏感词
    // 在不调整fail指针的情况下先构造好Trie树
    public void insert(String s) {
        char[] str = s.toCharArray();
        Node cur = root;
        for (char c : str) {
            int index = c - 'a';
            if (cur.nexts[index] == null) {
                cur.nexts[index] = new Node();
            }
            cur = cur.nexts[index];
        }
        cur.end = s;
    }
    // 设置好fail指针
    // 如果对这里不是很理解,可以网上找个动态图看看就明白了,
    // 光口头表达对于这个来说确实不好表达清楚,
    // 虽然我理解这过程但我现在还不会画动图,感觉对不起大家呀,有空一定学学咋画
    public void build() {
        LinkedList<Node> list = new LinkedList<>(); // 用于层序遍历
        list.add(root);
        while (!list.isEmpty()) { // 经典的层序遍历
            Node cur = list.poll();
            // 在当前节点时去设置nexts中节点的fail指针
            for (int i = 0; i < 26; i++) {
                if (cur.nexts[i] != null) {
                    // 先让它指向root节点
                    cur.nexts[i].fail = root;
                    // 去看 cFail 节点的子节点能否成为 cur.nexts[i]失配指针指向的节点
                    Node cFail = cur.fail;
                    while (cFail != null) {
                        if (cFail.nexts[i] != null) {
                            cur.nexts[i].fail = cFail.nexts[i];
                            break;
                        }
                        cFail = cFail.fail;
                    }
                    list.add(cur.nexts[i]);
                }
            }
        }
    }
    // 收集content中出现过的敏感词
    public List<String> containWords(String content) {
        char[] str = content.toCharArray();
        ArrayList<String> res = new ArrayList<>();
        Node cur = root;
        for (char c : str) {
            int index = c - 'a';
            while (cur.nexts[index] == null && cur != root) {
                cur = cur.fail;
            }
            cur = cur.nexts[index] != null ? cur.nexts[index] : root;
            Node follow = cur;
            while (follow != root) {
                if (follow.endUse) { // 如果已经收集过了就不再收集了
                    break;
                }
                if (follow.end != null) {
                    res.add(follow.end);
                    follow.endUse = true;
                }
                follow = follow.fail;
            }
        }
        return res;
    }
}


目录
相关文章
|
机器学习/深度学习 分布式计算 并行计算
MaxCompute-udf用于torch离线模型批量推理
odps-udf用于torch离线模型的批量推理实现以及踩坑
|
SQL 关系型数据库 MySQL
你学会如何将项目部署到Linux系统上了吗?
Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。
你学会如何将项目部署到Linux系统上了吗?
|
12月前
|
消息中间件 监控 Java
微软一面:订单超时未支付,如何自动关闭?
本文探讨了微软面试中关于订单超时自动关闭的设计题,提供了四种解决方案:定时器轮询、被动关闭、MQ延时消息及分布式超时中心。每种方案均详细阐述了实现思路、优缺点及适用场景。强调架构应基于业务需求,而非盲目追求高大上。适合不同规模的企业参考选用。
340 4
EMQ
|
存储 JSON 数据库
MQTTX 1.10.0 发布:CLI高级文件管理与配置
在本次更新中,CLI 版本在文件管理和配置功能方面进行了显著增强。主要更新包括:支持从文件中读取和写入消息、高级配置选项、文本输出模式、以及改进的日志记录。此外,桌面版本现在支持数据库重建,以防止文件损坏引起的问题,并且能更好地处理大数据的展示。这些更新希望为所有 MQTTX 用户提供更加强大和用户友好的体验。
EMQ
779 93
MQTTX 1.10.0 发布:CLI高级文件管理与配置
|
运维 芯片
主板电源符号揭秘:深入了解VDD、VDDQ、5VSB及其他
本文介绍了计算机主板电源设计中的关键符号,包括VDD(通用数字电路电源)、VDDQ(高稳定度滤波电源)、5VSB和3VSB(待机电源)、VCC3(+3V主要电源)、VDIMM(内存专用电源)、SB(待机电池电源)以及VCORE(CPU核心电压)。这些电源符号各自对应特定的供电区域和功能,确保主板组件的稳定运行。理解这些电源符号对于主板电源管理、故障排查和系统优化具有重要意义。
|
SQL 缓存 关系型数据库
MySQL(三)SQL优化、Buffer pool、Change buffer
MySQL(三)SQL优化、Buffer pool、Change buffer
329 0
|
Linux UED iOS开发
[√]pyinstaller打包的exe运行报错,找不到库
[√]pyinstaller打包的exe运行报错,找不到库
619 0
|
开发框架 前端开发 JavaScript
当年很流行,现在已经淘汰的前端技术有哪些?
当年很流行,现在已经淘汰的前端技术有哪些?
599 0
Pure admin-Router标签页配置以及页面持久化
Pure admin-Router标签页配置以及页面持久化
656 0