P3796 【模板】AC自动机(加强版)
分析:
AC自动机。
建出AC自动机,然后扫一遍文本串,顺着last,统计每个模式串出现的次数。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 const int N = 150100; 6 7 char str[1000100], s[155][75]; 8 9 int ch[N][26], fail[N], val[N], ans[N], q[N], last[N], L, R, Index; 10 11 void clear() { 12 memset(ch, 0, sizeof(ch)); 13 memset(val, 0, sizeof(val)); 14 memset(ans, 0, sizeof(ans)); 15 memset(last, 0, sizeof(last)); 16 memset(fail, 0, sizeof(fail)); 17 Index = 0; 18 } 19 void Insert(char *s,int ID) { 20 int u = 0, len = strlen(s); 21 for (int i=0; i<len; ++i) { 22 int c = s[i] - 'a'; 23 if (!ch[u][c]) ch[u][c] = ++Index; 24 u = ch[u][c]; 25 } 26 val[u] = ID; 27 } 28 void build() { 29 L = 1, R = 0; fail[0] = 0; 30 for (int c=0; c<26; ++c) { 31 int u = ch[0][c]; 32 if (u) fail[u] = 0, q[++R] = u, last[u] = 0; 33 } 34 while (L <= R) { 35 int u = q[L++]; 36 for (int c=0; c<26; ++c) { 37 int v = ch[u][c]; 38 if (!v) { 39 ch[u][c] = ch[fail[u]][c]; 40 continue; 41 } 42 q[++R] = v; 43 int p = fail[u]; 44 while (p && !ch[p][c]) p = fail[p]; 45 fail[v] = ch[p][c]; 46 last[v] = val[fail[v]] ? fail[v] : last[fail[v]]; 47 } 48 } 49 } 50 void find(char *s) { 51 int Ans = 0, u = 0, len = strlen(s); 52 for (int i=0; i<len; ++i) { 53 int c = s[i] - 'a'; 54 u = ch[u][c]; 55 if (val[u]) ans[val[u]] ++; 56 int p = u; 57 while (last[p]) { 58 p = last[p]; 59 if (val[p]) ans[val[p]] ++; 60 } 61 } 62 } 63 int main () { 64 int n; 65 while (~scanf("%d",&n) && n) { 66 clear(); 67 for (int i=1; i<=n; ++i) { 68 scanf("%s",s[i]); 69 Insert(s[i], i); 70 } 71 build(); 72 scanf("%s",str); 73 find(str); 74 int mx = 0; 75 for (int i=1; i<=n; ++i) mx = max(ans[i], mx); 76 printf("%d\n",mx); 77 for (int i=1; i<=n; ++i) { 78 if (ans[i] == mx) printf("%s\n",s[i]); 79 } 80 } 81 return 0; 82 }