AC自动机模板
经典例题
Keywords Search HDU - 2222
【求目标串中出现了几个模式串】
【(注意:模式串可能会重复)】
模板:
1 const int maxn=26;
2 struct Trie
3 {
4 int next[500010][maxn];
5 int fail[500010],end[500010];
6 int root,L;
7 int newnode() //初始化
8 {
9 for(int i=0;i<26;i++)
10 next[L][i]=-1;
11 end[L++]=0;
12 return L-1;
13 }
14
15 void init()//初始化
16 {
17 L=0;
18 root=newnode();
19 }
20 void insert(char s[])//构造树trie
21 {
22 int len=strlen(s);
23 int now=root;
24 for(int i=0;i<len;i++)
25 {
26 if(next[now][s[i]-'a']==-1)
27 next[now][s[i]-'a']=newnode();
28 now=next[now][s[i]-'a'];
29 }
30 end[now]++;
31 }
32
33 void build()//构造失败指针
34 {
35 queue<int>Q;
36 fail[root]=root;
37 for(int i=0;i<26;i++)
38 if(next[root][i]==-1)
39 next[root][i]=root;
40 else
41 {
42 fail[next[root][i]]=root;
43 Q.push(next[root][i]);
44 }
45 while(!Q.empty())
46 {
47 int now=Q.front();
48 Q.pop();
49 for(int i=0;i<26;i++)
50 if(next[now][i]==-1)
51 next[now][i]=next[fail[now]][i];
52 else
53 {
54 fail[next[now][i]]=next[fail[now]][i];
55 Q.push(next[now][i]);
56 }
57
58 }
59 }
60
61 void query(char buf[])//查询
62 {
63 int len=strlen(buf);
64 int now=root;
65 int sum=0;
66 for(int i=0;i<len;i++)
67 {
68 now = next[now][buf[i]-'a'];
69 int temp = now;
70 while(temp != root)
71 {
72
73 sum+=end[temp];
74 end[temp]=0;//避免重复计算
75 temp = fail[temp];
76 }
77 }
78 printf("%d\n",sum);
79 }
80 };
病毒侵袭 HDU - 2896
【统计目标串中模式串的个数】
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<queue>
6 #include<vector>
7 #include<cmath>
8 #include<string>
9 #include<map>
10 #define LL long long
11 using namespace std;
12 const int maxn=128;//模板部分
13 struct Trie
14 {
15 int next[210*500][maxn];
16 int fail[210*500],end[210*500];
17 int root,L;
18 int newnode() //初始化
19 {
20 for(int i=0;i<128;i++)
21 next[L][i]=-1;
22 end[L++]=-1;
23 return L-1;
24 }
25
26 void init()//初始化
27 {
28 L=0;
29 root=newnode();
30 }
31 void insert(char s[],int id)//构造树trie
32 {
33 int len=strlen(s);
34 int now=root;
35 for(int i=0;i<len;i++)
36 {
37 if(next[now][s[i]]==-1)
38 next[now][s[i]]=newnode();
39 now=next[now][s[i]];
40 }
41 end[now]=id;//记录单词的id
42 }
43
44 void build()//构造失败指针
45 {
46 queue<int>Q;
47 fail[root]=root;
48 for(int i=0;i<128;i++)
49 if(next[root][i]==-1)
50 next[root][i]=root;
51 else
52 {
53 fail[next[root][i]]=root;
54 Q.push(next[root][i]);
55 }
56 while(!Q.empty())
57 {
58 int now=Q.front();
59 Q.pop();
60 for(int i=0;i<128;i++)
61 if(next[now][i]==-1)
62 next[now][i]=next[fail[now]][i];
63 else
64 {
65 fail[next[now][i]]=next[fail[now]][i];
66 Q.push(next[now][i]);
67 }
68
69 }
70 }
71
72
73 bool vis[510];
74 bool query(char buf[],int n,int id)//查询
75 {
76 int len=strlen(buf);
77 int now=root;
78 memset(vis,0,sizeof(vis));
79 bool flag=false;
80 for(int i=0;i<len;i++)
81 {
82 now = next[now][buf[i]];
83 int temp = now;
84 while(temp != root)
85 {
86 if(end[temp] != -1)
87 {
88 vis[end[temp]] = true;
89 flag = true;
90 }
91 temp = fail[temp];
92 }
93 }
94 if(!flag)return false;
95 printf("web %d:",id);
96 for(int i = 1;i <= n;i++)
97 if(vis[i])
98 printf(" %d",i);
99 printf("\n");
100 return true;
101 }
102 };
103 char str1[205];
104 char str2[10010];
105 Trie ac;
106 int main()
107 {
108 int n,m;
109 while(scanf("%d",&n) != EOF)
110 {
111 ac.init();
112 for(int i = 1;i <= n;i++)
113 {
114 scanf("%s",str1);
115 ac.insert(str1,i);
116 }
117 ac.build();
118 int ans = 0;
119 scanf("%d",&m);
120 for(int i = 1;i <= m;i++)
121 {
122 scanf("%s",str2);
123 if(ac.query(str2,n,i))
124 ans++;
125 }
126 printf("total: %d\n",ans);
127 }
128 return 0;
129 }
病毒侵袭持续中 HDU - 3065
【思路:和病毒侵袭 HDU - 2896 这题差不多,只是多了一个计数。】
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<queue>
6 #include<vector>
7 #include<cmath>
8 #include<string>
9 #include<map>
10
11 using namespace std;
12 #define int long long
13 const int maxn=128;
14
15 char str1[1010][100];
16 char str2[2000005];
17
18 char STR[1003][66];
19 char SSS[2000100];
20 struct Trie{
21 int next[2010*50][maxn];
22 int fail[2010*50],end[2010*50];
23 int root,L;
24 int newnode() //初始化
25 {
26 for(int i=0;i<128;i++)
27 next[L][i]=-1;
28 end[L++]=-1;
29 return L-1;
30 }
31
32 void init()//初始化
33 {
34 L=0;
35 root=newnode();
36 }
37 void insert(char s[],int id)//构造树trie
38 {
39 int len=strlen(s);
40 int now=root;
41 for(int i=0;i<len;i++)
42 {
43 if(next[now][s[i]]==-1)
44 next[now][s[i]]=newnode();
45 now=next[now][s[i]];
46 }
47 end[now]=id;//记录单词的id
48 }
49
50 void build()//构造失败指针
51 {
52 queue<int>Q;
53 fail[root]=root;
54 for(int i=0;i<128;i++)
55 if(next[root][i]==-1)
56 next[root][i]=root;
57 else
58 {
59 fail[next[root][i]]=root;
60 Q.push(next[root][i]);
61 }
62 while(!Q.empty())
63 {
64 int now=Q.front();
65 Q.pop();
66 for(int i=0;i<128;i++)
67 if(next[now][i]==-1)
68 next[now][i]=next[fail[now]][i];
69 else
70 {
71 fail[next[now][i]]=next[fail[now]][i];
72 Q.push(next[now][i]);
73 }
74
75 }
76 }
77
78
79 int vis[1666];//记录出现的次数
80 void query(char buf[],int n)//查询
81 {
82 int len=strlen(buf);
83 int now=root;
84 memset(vis,0,sizeof(vis));
85 bool flag=false;
86 for(int i=0;i<len;i++)
87 {
88 now = next[now][buf[i]];
89 int temp = now;
90 while(temp != root)
91 {
92 if(end[temp] != -1)
93 {
94 vis[end[temp]]++;
95 flag = true;
96 }
97 temp = fail[temp];
98 }
99 }
100 if(flag ){
101 for(int i=1;i<=n;i++){
102 if(vis[i]){
103 printf("%s: %lld\n",STR[i],vis[i]);
104 }
105 }
106 }
107 return ;
108
109
110 }
111 }AC;
112
113 signed main(){
114 int n;
115
116 while(~scanf("%lld",&n)){
117
118 AC.init();
119 for(int i=1;i<=n;i++){
120 scanf("%s",STR[i]);
121 AC.insert(STR[i],i);
122 }
123 AC.build();
124 scanf("%s",SSS);
125 AC.query(SSS,n);
126 }
127 return 0;
128 }
来源:https://www.cnblogs.com/pengge666/p/12207713.html