AC自动机模板

经典例题

Keywords Search HDU - 2222

【求目标串中出现了几个模式串】

【(注意:模式串可能会重复)】

模板:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
 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 }
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄