模板AC自动机(简单版)

Posted fighting-sh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板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 }
View Code

 


以上是关于模板AC自动机(简单版)的主要内容,如果未能解决你的问题,请参考以下文章

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

模板AC自动机(简单版)

[LuoguP3808] 模板AC自动机(简单版)数组版

模板AC自动机(简单版)

模板AC自动机(简单版)

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