luogu P3796【模板】AC自动机(加强版)

嘟嘟嘟

 

这个和某谷的AC自动机模板简单版差不多。

但还是要注意几点的:

1.这个是统计出现次数,而不是是否出现,所以在查询的时候加上这个节点的val后,不能把val标记为-1。那么也就可以说查询的时间复杂度能比简单版的稍微第一慢一点。

2.考虑k个一样的模式串:刚开始我想的是每一个节点开一个vector,记录这里是第几个模式串。但其实没有这个必要,对于相同的模式串,我们只用记录任意一个就行,反而在出现次数上要都加上。因为如果主串中存在这些相同的模式串,那么出现次数应该是出现次数 * k。输出的时候如果是这些串最多,那么都应该把这些输出。

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<queue>
 10 #include<assert.h>
 11 #include<ctime>
 12 using namespace std;
 13 #define enter puts("") 
 14 #define space putchar(' ')
 15 #define Mem(a, x) memset(a, x, sizeof(a))
 16 #define In inline
 17 #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
 18 typedef long long ll;
 19 typedef double db;
 20 const int INF = 0x3f3f3f3f;
 21 const db eps = 1e-8;
 22 const int maxs = 1e6 + 5;
 23 const int maxn = 155;
 24 const int maxN = 1.1e4 + 5;
 25 In ll read()
 26 {
 27     ll ans = 0;
 28     char ch = getchar(), las = ' ';
 29     while(!isdigit(ch)) las = ch, ch = getchar();
 30     while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
 31     if(las == '-') ans = -ans;
 32     return ans;
 33 }
 34 In void write(ll x)
 35 {
 36     if(x < 0) x = -x, putchar('-');
 37     if(x >= 10) write(x / 10);
 38     putchar(x % 10 + '0');
 39 }
 40 In void MYFILE()
 41 {
 42 #ifndef mrclr
 43     freopen(".in", "r", stdin);
 44     freopen(".out", "w", stdout);
 45 #endif
 46 }
 47 
 48 int n;
 49 char s[maxs], s2[maxn][100];
 50 
 51 int sum[maxn];
 52 int ch[maxN][26], val[maxN], pos[maxN], f[maxN], cnt = 0;
 53 In int C(char c) {return c - 'a';}
 54 In void Clear(int x) {Mem(ch[x], 0), val[x] = pos[x] = f[x] = 0;}
 55 In void insert(int id, char* s)
 56 {
 57     int len = strlen(s), now = 0;
 58     for(int i = 0; i < len; ++i)
 59     {
 60         int c = C(s[i]);
 61         if(!ch[now][c]) Clear(++cnt), ch[now][c] = cnt;
 62         now = ch[now][c];
 63     }
 64     val[now]++, pos[now] = id;
 65 }
 66 In void build()
 67 {
 68     queue<int> q;
 69     for(int i = 0; i < 26; ++i) if(ch[0][i]) q.push(ch[0][i]);
 70     while(!q.empty())
 71     {
 72         int now = q.front(); q.pop();
 73         for(int i = 0; i < 26; ++i)
 74         {
 75             if(ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]);
 76             else ch[now][i] = ch[f[now]][i];
 77         }
 78     }
 79 }
 80 In void query(char* s)
 81 {
 82     int len = strlen(s), now = 0;
 83     for(int i = 0; i < len; ++i)
 84     {
 85         int c = C(s[i]);
 86         now = ch[now][c];
 87         for(int j = now; j; j = f[j]) sum[pos[j]] += val[j];
 88     }
 89 }
 90 
 91 In void init()
 92 {
 93     Clear(cnt = 0), Mem(sum, 0);
 94 }
 95 
 96 int main()
 97 {
 98 //    MYFILE();
 99     while(scanf("%d", &n) && n)
100     {
101         init();
102         for(int i = 1; i <= n; ++i)
103         {
104             scanf("%s", s2[i]);
105             insert(i, s2[i]);
106         }
107         build();
108         scanf("%s", s);
109         query(s);
110         int Max = -1;
111         for(int i = 1; i <= n; ++i) Max = max(Max, sum[i]);
112         write(Max), enter;
113         for(int i = 1; i <= n; ++i)    if(sum[i] == Max) puts(s2[i]);
114     }
115     return 0;
116 }

 

posted @ 2018-10-10 19:32  mrclr  阅读(244)  评论(1编辑  收藏  举报