题意:
给定几个模式串,看是否出现在主串中,如果出现在主串,输出这些模式串的标号。
解析:
AC自动机裸题。
用所给的模式串构建AC自动机,然后用主串去匹配。
将匹配到的结果插入set中,最后输出set。
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
const int maxnode = 501 * 201;
const int sigma_size = 127 - 31;
const int MAXN = 205;
set<int> ans;
set<int>::iterator it;
struct AC {
int ch[maxnode][sigma_size];
int fail[maxnode];
int last[maxnode];
int val[maxnode];
int sz;
void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
inline int idx(char c) { return c - 31; }
void insert(char* s, int v = 1) {
int u = 0, n = strlen(s);
for(int i = 0; i < n; 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 getFail() {
queue<int> que;
fail[0] = 0;
for(int c = 0; c < sigma_size; c++) {
int u = ch[0][c];
if(u) { fail[u] = last[u] = 0; que.push(u); }
}
while(!que.empty()) {
int r = que.front(); que.pop();
for(int c = 0; c < sigma_size; c++) {
int u = ch[r][c];
if(!u) continue;
que.push(u);
int v = fail[r];
while(v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}
void find(char *s) {
int n = strlen(s);
int v = 0;
ans.clear();
for(int i = 0; i < n; i++) {
int c = idx(s[i]);
while(v && !ch[v][c]) v = fail[v];
v = ch[v][c];
if(val[v]) print(v);
else if(last[v]) print(last[v]);
}
}
void print(int u) {
while(u) {
ans.insert(val[u]);
u = last[u];
}
}
} ac;
char key[MAXN];
char tar[10005];
int n, m;
int main() {
while(~scanf("%d", &n)) {
ac.clear();
for(int i = 1; i <= n; i++) {
scanf("%s", key);
ac.insert(key, i);
}
ac.getFail();
scanf("%d", &m);
int tot = 0;
for(int i = 1; i <= m; i++) {
scanf("%s", tar);
ac.find(tar);
if(ans.size() > 0) {
tot++;
printf("web %d:", i);
for(it = ans.begin(); it != ans.end(); it++)
printf(" %d", *it);
puts("");
}
}
printf("total: %d\n", tot);
}
return 0;
}