询问每个模式串在文本传中出现的次数。
文本串中出现的字符不一定都是大写字母,只需要在匹配的时候,对文本串进行特殊处理,将连续的大写字母段当成合法的一个文本串即可。
然后……就是简单的统计了。
#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 ", s[i], cnt[i]); } return 0; }