IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【算法与数据结构】——AC自动机 -> 正文阅读

[数据结构与算法]【算法与数据结构】——AC自动机

参考文章AC自动机
感觉这篇文章讲的十分简洁易懂,但是好像有点地方的表述有点错误。我决定根据自己的理解再复述一次整个ac自动机的思路

AC自动机

ac自动机是在字典树和KMP算法的基础上进行拓展的,KMP算法属于是单模匹配算法,AC自动机属于是多模匹配算法。

原理

首先给定模式串"ash",“shex”,“bcd”,“sha”
在这里插入图片描述
AC自动机就是在trie树的基础上,增加一个fail指针(相当于kmp中的next数组),如果当前点匹配失败,则将指针转移到fail指针指向的地方,这样就不用回溯,而可以路匹配下去了。

一般fail指针的构建是用bfs实现的,首先每个模式串的首字母肯定是指向根节点的。
在这里插入图片描述
现在第一层bfs遍历完了,开始第二层
(根节点为第0层)第二层a的子节点为s,但是我们还是要从a-z遍历,如果不存在这个子节点我们就让这个子节点指向当前节点fail指针的这个子节点)
请添加图片描述
当我们遍历当前节点子节点遍历到s的时候,由于存在s这个节点,我们就让s这个子节点的fail指针指向当前节点(a)的fail指针指向的那个节点的具有相同字母的子节点(第一层的s),也就是这样
请添加图片描述
后面的层规则与之前是相同的,以此类推即可。
完全构造好的树是这样的。
请添加图片描述
关于字符串匹配的过程就是跟kmp算法是一样的了,遇到适配字符就跳转到fail指针指向的位置即可。

模板

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e6+6;
int trie[N][26];
int tot;
int cntword[N];
int fail[N];
void insertWords(string str)
{
    int p=0;
    for(int i = 0;i < str.size();i++)
    {
        int next = str[i]-'a';
        if(trie[p][next]==0)
        {
            trie[p][next]=++tot;
        }
        p=trie[p][next];
    }
    cntword[tot]++;
}
void getFail()
{
    queue<int> q;
    for(int i=0;i < 26;i++)
    {
        if(trie[0][i])
        {
            fail[trie[0][i]]=0;
            q.push(trie[0][i]);
        }
    }

    while(!q.empty())
    {
        int now= q.front();
        q.pop();

        for(int i = 0;i < 26;i++)
        {
            if(trie[now][i]){//子节点存在
                fail[trie[now][i]]=trie[fail[now]][i];
                q.push(trie[now][i]);
            }
            else//子节点不存在
            {
                trie[now][i]=trie[fail[now]][i];
            }
        }
    }
}
int query(string s)//查询字符串s中有几个单词
{
    int now = 0,ans = 0;
    for(int i=0;i<s.size();i++){
        now = trie[now][s[i]-'a'];
        for(int j=now;j && cntword[j]!=-1;j=fail[j]){
            ans += cntword[j];
            cntword[j] = -1;
        }
    }
    return ans;
}

int main()
{
    insertWords("in");
    insertWords("name");
    insertWords("na");
    insertWords("string");
    insertWords("int");
    fail[0] = 0;
    getFail();
    cout << query("nameisinstring") << endl;//4
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-22 20:49:54  更:2022-03-22 20:52:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:27:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码