[洛谷P3796][题解][模板]AC自动机

至于AC自动机基础的话推荐yyb's blog

如果看了还是不会的话就像我一样啃一整天画个图想一想就好啦

AC自动机其实就是一种多模匹配算法,他约等于KMP思想+Trie结构(反正说了也没用)

这道题主要是注意统计答案,可以在标记end时记上顺序并在统计答案时用结构体记录

然后数据有很多组注意清零(我因为ans没清零WA了n次)

Code:(与yyb的代码有相似之处毕竟是看着学的嘛

 1 #include<bits/stdc++.h>
 2 #define debug cout<<"AJH AK IOI!!!"<<endl
 3 using namespace std;
 4 int cnt,n;
 5 string ss[160];
 6 struct Node {
 7     int fail,ed,son[26];
 8 }tr[100510];
 9 struct Ans {//统计答案,ct为出现次数,idx为编号(输出用) 
10     int ct,idx;
11 }ans[100510];
12 inline bool cmp(Ans a,Ans b){
13     if(a.ct==b.ct)return a.idx<b.idx;
14     return a.ct>b.ct;
15 }
16 inline void Clear(int now){
17     tr[now].ed=0;
18     tr[now].fail=0;
19     memset(tr[now].son,0,sizeof(tr[now].son));
20 }
21 inline void Insert(string s,int nownum){
22     int len=s.length(),now=0,tmp;
23     for(int i=0;i<len;i++){
24         tmp=s[i]-'a';
25         if(!tr[now].son[tmp]){
26             tr[now].son[tmp]=++cnt;//AC自动机基础操作,注意清零 
27             Clear(cnt);
28         }
29         now=tr[now].son[tmp];
30     }
31     tr[now].ed=nownum;//插入单词时记录顺序 
32 }
33 inline void Fail(){
34     queue<int>q;
35     for(int i=0;i<26;i++){
36         if(tr[0].son[i]){
37             tr[tr[0].son[i]].fail=0;
38             q.push(tr[0].son[i]);
39         }
40     }
41     while(!q.empty()){
42         int now=q.front();
43         q.pop();
44         for(int i=0;i<26;i++){
45             if(tr[now].son[i]){
46                 tr[tr[now].son[i]].fail=tr[tr[now].fail].son[i];
47                 //非常巧妙的操作,避免了一步一步向上跳
48                 //可以想一想为什么(其实我也没搞懂但是这行代码太好背了) 
49                 q.push(tr[now].son[i]);
50             } else{
51                 tr[now].son[i]=tr[tr[now].fail].son[i];
52             }
53         }
54     }
55 }
56 inline void Find(string s){
57     int len=s.length(),now=0,tmp;
58     for(int i=0;i<len;i++){
59         tmp=s[i]-'a';
60         now=tr[now].son[tmp];
61         for(int j=now;j;j=tr[j].fail){
62             ans[tr[j].ed].ct++;//找完一个单词记到ans里 
63         }
64     }
65 }
66 int main(){
67       while(114514){//这里可能有点臭 
68         cin>>n;
69         if(n==0)break;
70         Clear(0);
71         cnt=0;
72         for(int i=1;i<=n;i++){
73             cin>>ss[i];
74             ans[i].ct=0;//这句话害我WA半天 
75             ans[i].idx=i;
76             Insert(ss[i],i);
77         }
78         Fail();
79         cin>>ss[0];
80         Find(ss[0]);
81         sort(ans+1,ans+n+1,cmp);
82         //输出结果 
83         cout<<ans[1].ct<<endl;
84         cout<<ss[ans[1].idx]<<endl;
85         for(int i=2;i<=n;i++){
86             if(ans[i].ct==ans[i-1].ct){
87                 cout<<ss[ans[i].idx]<<endl;
88             }else break;
89         }
90         //////////
91     }
92     return 0;//功德園满 
93 }
内容来自_ajhfff_的博客(https://www.cnblogs.com/juruoajh/),未经允许,不得转载。
原文地址:https://www.cnblogs.com/juruoajh/p/12238826.html