参考:《算法竞赛入门经典-训练指南》
在模式匹配问题中,如果模板有多个,KMP 算法就不太适合了
1、UVALive 4670 Dominating Patterns
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <bitset>
#include <ctime>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pair;
const int INF = 0x7fffffff;
const int maxn = 1e6 + 10;
map<string, int> mp;
struct AC_Automata {
int ch[maxn][26], fail[maxn], val[maxn], last[maxn];
int cnt[160];
int size;
void init() {
size = 1;
memset(ch[0], 0, sizeof(ch[0]));
memset(cnt, 0, sizeof(cnt));
mp.clear();
}
int idx(char c) { return c - 'a'; };
void insert(char* s, int _val);
void find(char* T);
void cnt_time(int j);
void get_fail(void);
};
char text[maxn], P[160][80];
int N;
AC_Automata ac;
int main() {
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H_
while (scanf("%d", &N) != EOF && N != 0) {
ac.init();
for (int i = 0; i < N; ++i) {
scanf("%s", P[i]);
ac.insert(P[i], i + 1);
}
ac.get_fail();
scanf("%s", text);
ac.find(text);
int Max = 0;
for (int i = 1; i <= N; ++i) {
Max = max(Max, ac.cnt[i]);
}
printf("%d\n", Max);
for (int i = 0; i < N; ++i) {
if (ac.cnt[mp[P[i]]] == Max) {
printf("%s\n", P[i]);
}
}
}
return 0;
}
void AC_Automata::get_fail(void) {
queue<int> q;
fail[0] = 0;
for (int c = 0; c < 26; ++c) {
int u = ch[0][c];
if (u) {
fail[u] = 0; q.push(u); last[u] = 0;
}
}
while (!q.empty()) {
int f = q.front(); q.pop();
for (int c = 0; c < 26; ++c) {
int u = ch[f][c];
if (!u) {
ch[f][c] = ch[fail[f]][c];
continue;
}
q.push(u);
int v = fail[f];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}
void AC_Automata::find(char* T) {
int len = strlen(T);
int j = 0;
for (int i = 0; i < len; ++i) {
int c = idx(T[i]);
while (j && !ch[j][c]) {
j = fail[j];
}
j = ch[j][c];
if (val[j]) {
cnt_time(j);
} else if (last[j]) {
cnt_time(last[j]);
}
}
}
void AC_Automata::cnt_time(int j) {
if (j) {
++cnt[val[j]];
cnt_time(last[j]);
}
}
void AC_Automata::insert(char* s, int _val) {
int u = 0, len = strlen(s);
for (int i = 0; i < len; ++i) {
int c = idx(s[i]);
if (!ch[u][c]) {
memset(ch[size], 0, sizeof(ch[size]));
val[size] = 0, ch[u][c] = size++;
}
u = ch[u][c];
}
val[u] = _val; mp[s] = _val;
}