题意:每个文本串的出现次数
分析:入门题,注意重复的关键字算不同的关键字,还有之前加过的清零。 新模板,加上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\n", ac.query (t));
}
return 0;
}