AC自动机

一.含义

AC自动机,著名的多模式串匹配算法之一。

AC自动机就是在Trie树上实现KMP算法

二.步骤

1.建树:将所有模式串构建成一棵Trie树

void add(char *s){
	int u=1,len=strlen(s);
	for(int i=0;i<len;i++){
		int c=s[i]-'a';
		if(!ch[u][c]){
			ch[u][c]=++cnt;
		}
		u=ch[u][c];
	}
	++ex[u];
	return ;
}

2.预处理失配指针nxt

void bfs(){//构建nxt指针,补全所有边转移 
	for(int i=0;i<26;i++)
		ch[0][i]=1;
		que[1]=1;nxt[1]=0;
		for(int q1=1,q2=1;q1<=q2;q1++){
			int u=que[q1];
			for(int i=0;i<26;i++){
				if(!ch[u][i]){
					ch[u][i]=ch[nxt[u]][i];
				}
				else {
					que[++q2]=ch[u][i];
					int v=nxt[u];
					nxt[ch[u][i]]=ch[v][i];
				}
			}
		}
	return ;
}

三.例题(模板)

题目:单词查询

题目描述
给定n个长度不超过50的由小写英文字母组成的单词用于查询,以及一篇长为m的文章,问:文中出现了多少个待查询的单词。

输入格式
第一行一个整数T,表示数据组数;

对于每组数据,第一行一个整数n,接下去n行表示n个单词,最后一行输入一个字符串,表示文章。

输出格式
对于每组数据,输出一个数,表示文中出现了多少个待查询的单词。

样例
输入样例
1
5
she
he
say
shr
her
yasherhs
输出样例
3
 

代码实现:(详解)

#include<bits/stdc++.h> 
// 包含了 C++ 标准库中的所有头文件,不推荐在实际编程中使用,可能会导致编译时间增加和潜在的命名冲突
using namespace std; 
// 使用 std 命名空间,使得在后续代码中可以直接使用其中的函数和对象,而无需加上 std:: 前缀

const int M=1e6+10; 
// 定义一个常量 M,表示一个较大的整数

char s[M]; 
// 定义一个字符数组 s,用于存储输入的字符串

int ch[M][27],nxt[M],que[M],ex[M],ans,cnt=1; 
// 定义多个整数数组 ch、nxt、que、ex,以及整数变量 ans 和 cnt,并初始化 cnt 为 1

void add(char *s){ 
// 定义一个名为 add 的函数,用于向 AC 自动机中添加字符串
    int u=1,len=strlen(s); 
    // 初始化一个节点索引 u 为 1,并获取输入字符串的长度
    for(int i=0;i<len;i++){ 
    // 遍历输入字符串
        int c=s[i]-'a'; 
        // 获取当前字符对应的索引
        if(!ch[u][c]){ 
        // 如果当前节点没有对应字符的子节点
            ch[u][c]=++cnt; 
            // 创建新的子节点,并更新节点计数
            memset(ch[cnt],0,sizeof(ch[cnt])); 
            // 清空新节点的子节点信息
        }
        u=ch[u][c]; 
        // 移动到当前字符对应的子节点
    }
    ++ex[u]; 
    // 标记当前节点为一个模式字符串的结束节点
    return ; 
    // 函数返回
}

void bfs(){ 
// 定义一个名为 bfs 的函数,用于构建 AC 自动机的 nxt 指针
    for(int i=0;i<26;i++)
        ch[0][i]=1; 
        // 将根节点的所有子节点初始化为 1
    que[1]=1;nxt[1]=0; 
    // 初始化队列,并设置根节点的 nxt 指针为 0
    for(int q1=1,q2=1;q1<=q2;q1++){ 
    // 进行广度优先搜索
        int u=que[q1]; 
        // 获取当前队列中的节点
        for(int i=0;i<26;i++){ 
        // 遍历所有可能的字符
            if(!ch[u][i]){ 
            // 如果当前节点没有该字符的子节点
                ch[u][i]=ch[nxt[u]][i]; 
                // 设置为父节点 nxt 指针对应位置的子节点
            }
            else { 
            // 如果有子节点
                que[++q2]=ch[u][i]; 
                // 将子节点加入队列
                int v=nxt[u]; 
                // 获取父节点的 nxt 指针指向的节点
                nxt[ch[u][i]]=ch[v][i]; 
                // 设置子节点的 nxt 指针
            }
        }
    }
    return ; 
    // 函数返回
}

void find(char *s){ 
// 定义一个名为 find 的函数,用于在 AC 自动机中查找输入字符串
    int u=1,len=strlen(s),k; 
    // 初始化节点索引、字符串长度和临时变量
    for(int i=0;i<len;i++){ 
    // 遍历输入字符串
        int c=s[i]-'a'; 
        // 获取当前字符的索引
        k=ch[u][c]; 
        // 获取当前字符对应的子节点
        while(k>1){ 
        // 当子节点不是根节点
            ans+=ex[k]; 
            // 累加结束节点的计数
            ex[k]=0; 
            // 清空结束节点的计数
            k=nxt[k]; 
            // 移动到 nxt 指针指向的节点
        }
        u=ch[u][c]; 
        // 移动到当前字符对应的子节点
    } 
    return ; 
    // 函数返回
}

int main(){ 
// 主函数,程序的入口点
    int t,n; 
    // 定义两个整数变量 t 和 n
    cin>>t; 
    // 从输入读取 t 的值
    while(t--){ 
    // 进行 t 次操作
        cin>>n; 
        // 读取每次操作中模式字符串的数量
        ans=0,cnt=1; 
        // 初始化结果变量和节点计数
        memset(ex,0,sizeof(ex)); 
        // 清空结束节点的计数数组
        for(int i=0;i<26;i++){
            ch[0][i]=1;
            ch[1][i]=0;
        } 
        // 初始化根节点和第一层节点的信息
        while(n--){
            cin>>s;
            add(s);
        } 
        // 读取 n 个模式字符串并添加到自动机中
        bfs(); 
        // 构建 nxt 指针
        cin>>s; 
        // 读取要查找的字符串
        find(s); 
        // 在自动机中查找
        cout<<ans<<endl; 
        // 输出查找结果
    }
    return 0; 
    // 程序正常结束返回 0
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python AC自动机是一个用于字符串匹配的算法,它可以高效地在一段文本中查找多个预定义的模式。它的实现可以使用多种库,其中包括ac自动机python和ahocorasick-python。 ac自动机python是一个对标准的ac自动机算法进行了完善和优化的实现,适用于主流的Python发行版,包括Python2和Python3。它提供了更准确的结果,并且可以通过pip进行安装,具体的安装方法可以参考官方文档或者使用pip install命令进行安装。 ahocorasick-python是另一个实现AC自动机的库,它也可以用于Python2和Python3。你可以通过官方网站或者GitHub源码获取更多关于该库的信息和安装指南。 对于AC自动机的使用,一个常见的例子是在一段包含m个字符的文章中查找n个单词出现的次数。要了解AC自动机,需要有关于模式树(字典树)Trie和KMP模式匹配算法的基础知识。AC自动机算法包括三个步骤:构造一棵Trie树,构造失败指针和模式匹配过程。在构造好AC自动机后,可以使用它来快速地在文本中查找预定义的模式,并统计它们的出现次数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ahocorasick-python:AC自动机python的实现,并进行了优化。 主要修复了 查询不准确的问题](https://download.csdn.net/download/weixin_42122986/18825869)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python实现多模匹配——AC自动机](https://blog.csdn.net/zichen_ziqi/article/details/104246446)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值