题意
给出n个单词的字典,给出一个文本串,求文本串中每个单词出现了多少次。
题解
AC自动机,还是卡空间。卵用memset就MLE,用不带last就TLE。
所以就改了一蛤。
代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int nmax = 50007;
const int sigma = 128;
int occ_times[nmax];
char dictionay[1001][51];
int n,m,cnt;
char str[2000001];
struct Aho {
int sz;
queue<int> que;
struct Node {
int nxt[sigma];
bool isocc;
int fail, id, last;
} node[nmax];
void init() {
memset(node[0].nxt, 0, sizeof node[0].nxt);
sz = 1;
}
inline int idx(const char & ch) {return ch;}
void insert(char * S, int id) {
int len = strlen(S);
int now = 0;
for(int i = 0; i < len; ++i) {
int c = idx(S[i]);
if(!node[now].nxt[c]) {
memset(node[sz].nxt, 0, sizeof node[sz].nxt);
node[sz].fail = node[now].isocc = node[sz].isocc = 0;
node[now].nxt[c] = sz++;
}
now = node[now].nxt[c];
}
node[now].isocc = true;
node[now].id = id;
}
void build_fail() {
node[0].fail = 0;
node[0].last = 0;
for (int i = 0; i < sigma; ++i) {
if (node[0].nxt[i]) {
node[node[0].nxt[i]].fail = 0;
node[node[0].nxt[i]].last = 0;
que.push(node[0].nxt[i]);
}
}
while(!que.empty()) {
int now = que.front(); que.pop();
for(int i = 0; i < sigma; ++i) {
int son = node[now].nxt[i];
if (!son) {
node[now].nxt[i] = node[node[now].fail].nxt[i];
continue;
}
que.push(son);
node[son].fail = node[node[now].fail].nxt[i];
node[son].last = node[node[now].fail].isocc ? node[son].fail : node[node[son].fail].last;
}
}
}
void getans(int u) {
while(u) {
if(node[u].isocc)
occ_times[node[u].id] ++;
u = node[u].last;
}
}
void match(char * S) {
int len = strlen(S);
int now = 0;
for(int i = 0; i < len; ++i) {
int c = idx(S[i]);
now = node[now].nxt[c];
if (node[now].isocc) {
getans(now);
} else if(node[now].last) {
getans(node[now].last);
}
}
}
} aho;
int main() {
while(scanf("%d", &n) != EOF) {
aho.init();
for(int i = 1; i <= n; ++i) {
scanf("%s", dictionay[i]);
aho.insert(dictionay[i], i);
occ_times[i] = 0;
}
aho.build_fail();
scanf("%s", str);
aho.match(str);
for (int i = 1; i <= n; ++i) {
if(occ_times[i] != 0) {
printf("%s: ", dictionay[i]);
printf("%d\n", occ_times[i]);
}
}
}
return 0;
}