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自动机入门题 求出现次数最多的子串

LightOJ 1427 Substring Frequency (II) (AC自动机)

子串查找

查找字符串的子串,使得子串的长度与其出现次数的乘积最大化

Java中查找子串出现次数