Java数据结构之AC自动机算法的实现

Java数据结构之AC自动机算法的实现

本文将详细讲解AC自动机算法在Java中的实现方法和原理,同时提供两个示例进行说明,使读者能够深入了解该算法并学会如何使用。

什么是AC自动机算法

AC自动机(Aho-Corasick Automaton)是多模式匹配的一种经典算法,其基本思路是将多个模式串构建成一颗“字典树”,然后对输入的文本串进行扫描匹配。相比于简单的暴力匹配方法,AC自动机算法可以在时间复杂度为O(n)的情况下实现多模式匹配,在诸如关键词过滤、字符串匹配等场景中具有很高的应用价值。

AC自动机算法的实现主要分为以下三个步骤:

  1. 构建trie树:将所有模式串构建成一个trie树;
  2. 对trie树进行预处理:为每个节点计算出其在trie树上的fail指针,并将所有模式串的状态存储到一个状态集合中;
  3. 使用AC自动机模式匹配算法:对输入的文本串进行扫描匹配,每遇到一个字符就在trie树上进行前缀匹配,并跟随其相应的fail指针回溯到其下一个状态,直到匹配成功或达到文本串的末尾。

Java实现

构建trie树

class TrieNode {
    Map<Character, TrieNode> children;
    boolean isEndOfWord;
    Set<String> patterns;

    public TrieNode() {
        this.children = new HashMap<>();
        this.isEndOfWord = false;
        this.patterns = new HashSet<>();
    }
}

class Trie {
    private TrieNode root;

    /**
     * Initialize your data structure here.
     */
    public Trie() {
        root = new TrieNode();
    }

    /**
     * Inserts a word into the trie.
     */
    public void insert(String word) {
        TrieNode curr = root;
        for (char c : word.toCharArray()) {
            curr.children.putIfAbsent(c, new TrieNode());
            curr = curr.children.get(c);
        }
        curr.isEndOfWord = true;
        curr.patterns.add(word); // 记录该节点所包含的所有模式串
    }
}

计算fail指针

class ACNode {
    char c; // 该节点代表的字符
    ACNode fail; // fail指针
    Map<Character, ACNode> children; // 子节点
    Set<String> patterns; // 存储该节点包含的所有模式串

    // 计算该节点的fail指针
    public void computeFailPointer() {
        Queue<ACNode> queue = new LinkedList<>();
        for (Map.Entry<Character, ACNode> entry : children.entrySet()) {
            char c = entry.getKey();
            ACNode child = entry.getValue();
            child.fail = this;
            queue.offer(child);
        }
        while (!queue.isEmpty()) {
            ACNode curr = queue.poll();
            for (Map.Entry<Character, ACNode> entry : curr.children.entrySet()) {
                char c = entry.getKey();
                ACNode child = entry.getValue();
                ACNode fail = curr.fail;
                while (fail != null && !fail.children.containsKey(c)) {
                    fail = fail.fail;
                }
                child.fail = fail == null ? this : fail.children.get(c);
                child.patterns.addAll(child.fail.patterns);
                queue.offer(child);
            }
        }
    }
}

class AC {
    private ACNode root;

    public AC(Trie trie) {
        root = new ACNode();
        for (Map.Entry<Character, TrieNode> entry : trie.root.children.entrySet()) {
            char c = entry.getKey();
            TrieNode child = entry.getValue();
            ACNode acChild = new ACNode();
            acChild.c = c;
            root.children.put(c, acChild);
            acChild.patterns.addAll(child.patterns);
            acChild.fail = root;
        }
        root.fail = root;
    }

    // 计算AC自动机的所有fail指针
    public void computeFailPointers() {
        root.computeFailPointer();
    }
}

AC自动机模式匹配

class ACAutomaton {
    private AC ac;

    public ACAutomaton(Trie trie) {
        ac = new AC(trie);
        ac.computeFailPointers();
    }

    public List<String> findAllOccurrences(String text) {
        List<String> res = new ArrayList<>();
        ACNode curr = ac.root;
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            while (curr != null && !curr.children.containsKey(c)) {
                curr = curr.fail;
            }
            if (curr == null) {
                curr = ac.root;
            } else {
                curr = curr.children.get(c);
                curr.patterns.forEach(res::add);
            }
        }
        return res;
    }
}

示例说明

示例一

假设有字符串集合{“she”, “he”, “say”, “sh”, “shr”, “her”},并且要在下面这段文本中找出所有的模式串:

she says he has her shrubs

对该文本进行扫描匹配,最终找出的模式串是:

she, he, her, shr, say

示例二

假设有字符串集合{“cc”, “ccc”, “cccc”},并且要在下面这段文本中找出所有的模式串:

abccccde

对该文本进行扫描匹配,最终找出的模式串是:

cc, ccc, cccc

总结

以上是AC自动机算法在Java中的实现方法和原理,本文详细讲解了AC自动机的实现过程和三个步骤,并同时提供了两个示例,希望能够帮助读者深入了解该算法并学会使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构之AC自动机算法的实现 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 自制PHP框架之模型与数据库

    很好,下面我将为您详细讲解如何自制PHP框架中的模型与数据库部分。 什么是模型和数据库? 在讲解自制PHP框架的模型和数据库前,我们需要先了解什么是模型和数据库。在PHP框架架构中,模型是用来操作数据库的一种机制,用来处理对数据表的增删改查等操作,并且与数据库的连接是一定的。而数据库是一种数据存储工具,用于存储数据并提供数据操作的方法,例如数据的增删改查等。…

    数据结构 2023年5月17日
    00
  • 详解python数据结构之队列Queue

    详解Python数据结构之队列 (Queue) 在计算机科学中,队列(Queue)是一种数据结构,可以用于按顺序存储和访问元素。该数据结构遵循先进先出(FIFO)原则,人们可以从队列的前面插入元素,从队列的后面删除元素。Python内置了队列模块(queue),这个模块实现了多线程安全队列、同步机制及相关数据结构。Queue模块提供了三种队列类型: FIFO…

    数据结构 2023年5月17日
    00
  • JoshChen_php新手进阶高手不可或缺的规范介绍

    JoshChen_php新手进阶高手不可或缺的规范介绍 作为一名PHP程序员,熟练掌握编程语言的同时,规范的代码风格也是不可或缺的。本文将介绍一些PHP规范的相关内容,帮助PHP新手进阶为高手。 1. 代码风格规范 1.1. 缩进 在编写代码时,缩进是非常重要的。按照规范,我们应该在每个缩进级别使用4个空格。 1.2. 命名规范 在PHP中,我们应该遵循以下…

    数据结构 2023年5月17日
    00
  • java中的PriorityQueue类过程详解

    Java中的PriorityQueue类过程详解 Java中的PriorityQueue类是一个基于优先级堆的无界优先级队列,它以小顶堆的形式来维护队列。在Java Collections Framework中,它实现了Queue接口,因此可以使用Queue的所有方法。 PriorityQueue类的基本性质 元素按照优先级排序:PriorityQueue类…

    数据结构 2023年5月17日
    00
  • [Week 19]每日一题(C++,数学,并查集,动态规划)

    目录 [Daimayuan] T1 倒数第n个字符串(C++,进制) 输入格式 输出格式 样例输入 样例输出 解题思路 [Daimayuan] T2 排队(C++,并查集) 输入格式 输出格式 样例输入1 样例输出1 样例输入2 样例输出2 样例输入3 样例输出3 数据规模 解题思路 [Daimayuan] T3 素数之欢(C++,BFS) 数据规模 输入格…

    算法与数据结构 2023年5月4日
    00
  • JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解

    JS中的算法与数据结构:二叉查找树(Binary Sort Tree) 什么是二叉查找树 二叉查找树(Binary Sort Tree),又称二叉搜索树或二叉排序树,是一种特殊的二叉树结构。它具有以下性质: 每个结点最多只有两个子结点。 左子树中的所有结点的值均小于它的根结点的值。 右子树中的所有结点的值均大于它的根结点的值。 没有相同节点值出现 因为具备以…

    数据结构 2023年5月17日
    00
  • Codeforces Round 868 Div 2

    A. A-characteristic (CF 1823 A) 题目大意 要求构造一个仅包含\(1\)和 \(-1\)的长度为 \(n\)的数组 \(a\),使得存在 \(k\)个下标对 \((i, j), i < j\)满足 \(a_i \times a_j = 1\)。 解题思路 当有\(x\)个 \(1\), \(y\)个 \(-1\)时,其满足…

    算法与数据结构 2023年4月30日
    00
  • Java数据结构之图(动力节点Java学院整理)

    Java数据结构之图是动力节点Java学院整理的一篇关于图的攻略教程,该教程包含以下主要内容: 一、图的定义 图是由若干个顶点以及它们之间的相互关系所构成的数学模型。它包含了许多实际生活中的应用,如社交网络、地图、电子邮件网络等。 二、图的存储方式 图的存储方式有两种:邻接矩阵和邻接表。 邻接矩阵 邻接矩阵以二维数组的形式存储图。对于有n个顶点的图,其邻接矩…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部