詢問每個模式串在文本傳中出現的次數。
文本串中出現的字符不一定都是大寫字母,只需要在匹配的時候,對文本串進行特殊處理,將連續的大寫字母段當成合法的一個文本串即可。
然後……就是簡單的統計了。
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
using namespace std;
int n, cnt[1010];
char s[1010][55], t[2000010], a[2000010];
struct AC_Automata {
#define N 60003
#define M 26
int ch[N][M], f[N], val[N], last[N], sz;
void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
int idx(char c) { return c-'A'; }
void insert(char s[], int v) {
int u = 0;
for (int i=0; s[i]; i++) {
int c = idx(s[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] = v;
}
void build() {
queue<int> q;
f[0] = 0;
for (int c=0; c<M; c++) {
int u = ch[0][c];
if (u) { f[u] = last[u] = 0; q.push(u); }
}
while (!q.empty()) {
int r = q.front(); q.pop();
for (int c=0; c<M; c++) {
int u = ch[r][c];
if (!u) { ch[r][c] = ch[f[r]][c]; continue; }
q.push(u);
f[u] = ch[f[r]][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}
void find(char s[]) {
int j = 0;
for (int i=0; s[i]; i++) {
int c = idx(s[i]);
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);
}
}
void print(int j) {
if (j) {
cnt[val[j]]++;
print(last[j]);
}
}
} ac;
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (scanf(" %d", &n) == 1) {
ac.clear();
memset(cnt, 0, sizeof(cnt));
getchar();
for (int i=1; i<=n; i++) {
gets(s[i]); ac.insert(s[i], i);
}
ac.build();
gets(t);
int j = 0;
bool flag = false;
for (int i=0; t[i]; i++) {
if (t[i] <= 'Z' && t[i] >= 'A') { flag = true; a[j++] = t[i]; }
else if (flag) {
a[j] = 0; j = 0;
flag = false;
ac.find(a);
}
}
if (flag) {
a[j] = 0; j = 0;
flag = false; ac.find(a);
}
for (int i=1; i<=n; i++)
if (cnt[i]) printf("%s: %d\n", s[i], cnt[i]);
}
return 0;
}