题意:每个文本串的出现次数
分析:入门题,注意重复的关键字算不同的关键字,还有之前加过的清零。 新模板,加上last跑快一倍
#include <bits/stdc++.h> struct AC { static const int NODE = 10000 * 50 + 5; static const int SIZE = 26; int ch[NODE][SIZE], fail[NODE], last[NODE]; int end[NODE]; int sz; void clear() { memset (ch[0], 0, sizeof (ch[0])); end[0] = 0; sz = 1; } int idx(char ch) { return ch - 'a'; } void insert(char *str) { int u = 0; for (int c, i=0; str[i]; ++i) { c = idx (str[i]); if (!ch[u][c]) { memset (ch[sz], 0, sizeof (ch[sz])); end[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } end[u]++; } void build() { fail[0] = 0; std::queue<int> que; for (int c=0; c<SIZE; ++c) { int u = ch[0][c]; if (u) { fail[u] = 0; last[u] = 0; que.push (u); } } while (!que.empty ()) { int r = que.front (); que.pop (); for (int c=0; c<SIZE; ++c) { int u = ch[r][c]; if (!u) { ch[r][c] = ch[fail[r]][c]; } else { fail[u] = ch[fail[r]][c]; last[u] = end[fail[u]] ? fail[u] : last[fail[u]]; que.push (u); } } } } int query(char *text) { int ret = 0, u = 0; for (int c, i=0; text[i]; ++i) { c = idx (text[i]); u = ch[u][c]; int t = u; while (t) { ret += end[t]; end[t] = 0; t = last[t]; } } return ret; } }; AC ac; char p[55], t[1000010]; int main(void) { //HDOJ 2222 Keywords Search int T; scanf ("%d", &T); while (T--) { int n; scanf ("%d", &n); ac.clear (); for (int i=1; i<=n; ++i) { scanf ("%s", p); ac.insert (p); } ac.build (); scanf ("%s", t); printf ("%d ", ac.query (t)); } return 0; }