题意:训练指南P216
分析:求出现最多次数的字串,那么对每个字串映射id,cnt记录次数求最大就可以了。
#include <bits/stdc++.h>
using namespace std;
const int N = 150 + 5;
const int NODE = N * 70;
const int LEN = 1e6 + 5;
const int SIZE = 26;
struct AC {
int ch[NODE][SIZE], fail[NODE], val[NODE], cnt[N], sz;
map<string, int> ms;
void clear(void) {
memset (ch[0], 0, sizeof (ch[0]));
memset (cnt, 0, sizeof (cnt));
sz = 1; val[0] = 0;
ms.clear ();
}
int idx(char c) {
return c - 'a';
}
void insert(char *P, int id) {
ms[string (P)] = id;
int u = 0;
for (int c, i=0; P[i]; ++i) {
c = idx (P[i]);
if (!ch[u][c]) {
memset (ch[sz], 0, sizeof (ch[sz]));
val[sz] = 0; ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = id;
}
void build(void) {
queue<int> que; fail[0] = -1;
int u;
for (int i=0; i<SIZE; ++i) {
u = ch[0][i];
if (u) {
fail[u] = 0; que.push (u);
}
}
while (!que.empty ()) {
u = que.front (); que.pop ();
for (int i=0; i<SIZE; ++i) {
int &v = ch[u][i];
if (!v) {
v = ch[fail[u]][i]; continue;
}
que.push (v);
fail[v] = ch[fail[u]][i];
}
}
}
void query(char *T) {
int u = 0, v;
for (int c, i=0; T[i]; ++i) {
c = idx (T[i]);
u = ch[u][c]; v = u;
cnt[val[v]]++;
}
}
}ac;
char pattern[N][75], text[LEN];
int n;
void solve(void) {
int best = -1;
for (int i=1; i<=n; ++i) {
if (ac.cnt[i] > best) best = ac.cnt[i];
}
printf ("%d\n", best);
for (int i=1; i<=n; ++i) {
if (ac.cnt[ac.ms[string (pattern[i])]] == best) {
printf ("%s\n", pattern[i]);
}
}
}
int main(void) {
while (scanf ("%d", &n) == 1) {
if (!n) break;
ac.clear ();
for (int i=1; i<=n; ++i) {
scanf ("%s", &pattern[i]);
ac.insert (pattern[i], i);
}
ac.build ();
scanf ("%s", &text);
ac.query (text);
solve ();
}
return 0;
}