AC自动机(查找子串各出现次数)
Posted culion-bear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机(查找子串各出现次数)相关的知识,希望对你有一定的参考价值。
1 #include <iostream> 2 #include <vector> 3 #include <cstring> 4 #include <string> 5 #include <cstdio> 6 #include <queue> 7 #include <algorithm> 8 #include <functional> 9 #include <map> 10 using namespace std; 11 #define lson (i<<1) 12 #define rson ((i<<1)|1) 13 typedef long long ll; 14 typedef unsigned int ul; 15 const int maxn = 40010; 16 const int mod = 10007; 17 int ans[1005]; 18 int tot; 19 struct Tire 20 { 21 int nex[1000*55][130],fail[1000*55],ed[1000*55]; 22 int root,L; 23 int newnode() 24 { 25 for(int i = 0; i < 130; i++) 26 nex[L][i] = -1; 27 ed[L++] = 0; 28 return L-1; 29 } 30 31 void ini() 32 { 33 L = 0,root = newnode(); 34 } 35 36 void inser(char buf[],int id) 37 { 38 int len = strlen(buf); 39 int now = root; 40 for(int i = 0; i < len; i++) 41 { 42 int ta = buf[i]; 43 if(nex[now][ta] == -1) 44 nex[now][ta] = newnode(); 45 now = nex[now][ta]; 46 } 47 ed[now] = id; 48 } 49 50 void build() 51 { 52 queue<int >q; 53 fail[root] = root; 54 for(int i = 0; i < 130; i++) 55 if(nex[root][i] == -1) 56 nex[root][i] = root; 57 else 58 { 59 fail[nex[root][i]] = root; 60 q.push(nex[root][i]); 61 } 62 while(!q.empty()) 63 { 64 int now = q.front(); 65 q.pop(); 66 for(int i = 0; i < 130; i++) 67 { 68 if(nex[now][i] == -1) 69 nex[now][i] = nex[fail[now]][i]; 70 else 71 { 72 fail[nex[now][i]] = nex[fail[now]][i]; 73 q.push(nex[now][i]); 74 } 75 } 76 } 77 } 78 79 void query(char buf[]) 80 { 81 tot = 0; 82 int cur = root; 83 int len = strlen(buf); 84 for(int i = 0; i < len; i++) 85 { 86 cur = nex[cur][(int)buf[i]]; 87 int tp = cur; 88 89 while(tp != root) 90 { 91 if(ed[tp]) 92 ans[ed[tp]]++; 93 tp = fail[tp]; 94 } 95 } 96 } 97 }; 98 99 Tire ac; 100 char buf[505][80]; 101 char to[1000100]; 102 int main() 103 { 104 int n; 105 while(scanf("%d",&n) != EOF) 106 { 107 if(n==0) break; 108 ac.ini(); 109 for(int i = 1; i <= n; i++) 110 { 111 scanf("%s",buf[i]); 112 ac.inser(buf[i],i); 113 } 114 ac.build(); 115 memset(ans,0,sizeof(ans)); 116 scanf("%s",to); 117 ac.query(to); 118 int Max=0; 119 for(int i = 1; i <= n; i++) 120 { 121 Max=max(Max,ans[i]); 122 } 123 cout<<Max<<endl; 124 for(int i=1;i<=n;i++){ 125 if(Max==ans[i]) cout<<buf[i]<<endl; 126 } 127 128 } 129 return 0; 130 }
以上是关于AC自动机(查找子串各出现次数)的主要内容,如果未能解决你的问题,请参考以下文章
Dominating Patterns (AC 自动鸡模版题, 出现次数最多的子串)
UVALive-4670 AC自动机入门题 求出现次数最多的子串