码迷,mamicode.com
首页 > 其他好文 > 详细

AC自动机【模板】+经典例题

时间:2020-01-17 23:01:51      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:指针   word   记录   模板   ++   单词   病毒   next   cstring   

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 }

AC自动机【模板】+经典例题

标签:指针   word   记录   模板   ++   单词   病毒   next   cstring   

原文地址:https://www.cnblogs.com/pengge666/p/12207713.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!