模板】AC自动机(简单版)

模板】AC自动机(简单版)

https://www.luogu.org/problemnew/show/P3808

这是一道简单的AC自动机模板题。

用于检测正确性以及算法常数。

为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。

管理员提示:本题数据内有重复的单词,且重复单词应该计算多次,请各位注意

题目描述

给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

输入输出格式

输入格式:

第一行一个n,表示模式串个数;

下面n行每行一个模式串;

下面一行一个文本串。

输出格式:

一个数表示答案

输入输出样例

输入样例#1

2
a
aa
aa

输出样例#1

2

说明

subtask1[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6,n=1;

subtask2[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6;

参考博客:http://www.cnblogs.com/cjyyb/p/7196308.html

听说有一种需要用trie树做,trie图不能做的题目??先mark下

关于失配指针的描述:从当前节点开始,沿着其父节点的失配指针不断向上跑,直到到达一个节点,它的儿子中有当前字母,然后把这两个一样的字母连起来。

首先要构建trie图,然后fail是在trie图上实现的,所以fail上的跳转是在模式串上的跳转,通过这样的跳转,可以快速找到相匹配的模式串

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define lson l,mid,rt<<1
 4 #define rson mid+1,r,rt<<1|1
 5 #define sqr(x) ((x)*(x))
 6 #define maxn 1000005
 7 typedef long long ll;
 8 typedef unsigned long long ull;
 9 const ull MOD=257;
10 /*#ifndef ONLINE_JUDGE
11         freopen("1.txt","r",stdin);
12 #endif */
13
14 struct tree{
15     int fail;
16     int vis[26];
17     int num;
18 }ac[1000005];
19
20 int cnt=0;
21
22 void build(string s){///建trie树
23     int len=s.length();
24     int now=0;
25     for(int i=0;i<len;i++){
26         if(ac[now].vis[s[i]-‘a‘]==0){
27             ac[now].vis[s[i]-‘a‘]=++cnt;
28         }
29         now=ac[now].vis[s[i]-‘a‘];
30     }
31     ac[now].num+=1;
32 }
33
34 void get_fail(){///构建成trie图
35     queue<int>Q;
36     for(int i=0;i<26;i++){
37         if(ac[0].vis[i]){
38             ac[ac[0].vis[i]].fail=0;
39             Q.push(ac[0].vis[i]);
40         }
41     }
42     while(!Q.empty()){
43         int u=Q.front();
44         Q.pop();
45         for(int i=0;i<26;i++){
46             if(ac[u].vis[i]){
47                 ac[ac[u].vis[i]].fail=ac[ac[u].fail].vis[i];
48                 Q.push(ac[u].vis[i]);
49             }
50             else{
51                 ac[u].vis[i]=ac[ac[u].fail].vis[i];///如果当前结点不存在,就指向父亲结点的fail指向的结点的子结点
52             }
53         }
54     }
55 }
56
57 int ac_query(string s){
58     int len=s.length();
59     int now=0,ans=0;
60     for(int i=0;i<len;i++){
61         now=ac[now].vis[s[i]-‘a‘];
62         for(int t=now;t&&ac[t].num!=-1;t=ac[t].fail){
63             ans+=ac[t].num;
64             ac[t].num=-1;
65         }
66     }
67     return ans;
68 }
69
70 int main(){
71     #ifndef ONLINE_JUDGE
72       //  freopen("1.txt","r",stdin);
73     #endif
74     //std::ios::sync_with_stdio(false);
75     string s;
76     int n;
77     cin>>n;
78     for(int i=0;i<n;i++){
79         cin>>s;
80         build(s);
81     }
82     ac[0].fail=0;
83     get_fail();
84     cin>>s;
85     cout<<ac_query(s)<<endl;
86 }

原文地址:https://www.cnblogs.com/Fighting-sh/p/10363605.html

时间: 2024-10-29 00:30:34

模板】AC自动机(简单版)的相关文章

[模板][P3808]AC自动机(简单版)

模板,详见代码: #include<bits/stdc++.h> using namespace std; const int mxn=1e7+5; char str[mxn],p[80]; queue<int > q; namespace Trie { int tot,fail[mxn],val[mxn]; int t[mxn][26]; void ins(char *s) { int len=strlen(s),u=0; for(int i=0;i<len;++i) {

[模板]洛谷T3808 AC自动机(简单版)

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<ctime> 6 #include<cstdlib> 7 8 #include<string> 9 #include<stack> 10 #include<queue> 11 #include<vector> 1

算法模板——AC自动机

实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有时候字典会相当稀疏,所以引入了chi和bro指针进行优化——其原理比较类似于邻接表,这个东西本身和next数组本质上是一致的,只是chi和bro用于遍历某一节点下的子节点,next用于查询某节点下是否有需要的子节点) 1 type 2 point=^node; 3 node=record 4 ex:

[模板]AC自动机(1)

题目描述 给定一个文本串和多个模式串,求有几个模式串出现在文本串中 #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 1000005 char s[MAXN]; int N; struct queue{ int que[MAXN];int head,tail; queue():head(1),tail(0){} inline void pop(){head++;} inline

模板——AC自动机

#include<bits/stdc++.h> using namespace std; struct nob{ int fail,son[27],ed; }a[1000000]; int cnt=0; void build (string s){ int now=0; for (int i=0; i<s.length(); i++){ if (a[now].son[s[i]-'a']==0) a[now].son[s[i]-'a']=++cnt; now=a[now].son[s[i]

AC自动机例题

P3808 [模板]AC自动机(简单版) [题目描述] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. #include<bits/stdc++.h> using namespace std; typedef long long LL; const int INF=1e9+7; inline LL read(){ register LL x=0,f=1;register char c=getchar(); while(c<48||c>57){if(c=='-')f=

AC自动机 P3808 P3796

第一次写AC自动机 简单版的这道题可以在进行匹配的时候剪一下枝,应为之前比配过了,不用在匹配了. #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <queue> using namespace std; const int MAXN=1e6+10; queue<int> que; struct AC{ int

BZOJ 题目3172: [Tjoi2013]单词(AC自动机||AC自动机+fail树||后缀数组暴力||后缀数组+RMQ+二分等五种姿势水过)

3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1890  Solved: 877 [Submit][Status][Discuss] Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词由小写字母组成,N<=200,单词长度不超过10^6

从Trie谈到AC自动机

ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字母,因此得名`字母树`. 出一张图让大家感受下. (image powered by SaiBu NaoCu) 上面那是一棵插入了 ape,app,applicant,application,bake,ban,banana 等词的Trie.红色结点表示接受态. 显然,查找时只需顺着链照下来,插入只需

[C#] 逆袭——自制日刷千题的AC自动机攻克HDU OJ

前言 做过杭电.浙大或是北大等ACM题库的人一定对“刷题”不陌生,以杭电OJ为例:首先打开首页(http://acm.hdu.edu.cn/),然后登陆,接着找到“Online Exercise”下的“Problem Archive”,然后从众多题目中选择一个进行读题.构思.编程.然后提交.最后查看题解状态,如果AC了表示这一题被攻克了,否则就要重做了~一般情况下,“刷题”要求精神高度集中且经验丰富,否则很难成功AC,有时候甚至做一题要浪费半天的时间!(有时网速卡了,比抢火车票还要急!) 楼主在