模板】AC自动机(简单版)
https://www.luogu.org/problemnew/show/P3808
这是一道简单的AC自动机模板题。
用于检测正确性以及算法常数。
为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。
管理员提示:本题数据内有重复的单词,且重复单词应该计算多次,请各位注意
题目描述
给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。
输入输出格式
输入格式:
第一行一个n,表示模式串个数;
下面n行每行一个模式串;
下面一行一个文本串。
输出格式:
一个数表示答案
输入输出样例
说明
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 }