题意:给定n个模式串,m个文本串 ,求每个文本串分别包含哪些模式串。
思路:在匹配一个文本串的时候,必须把访问过的节点标记,否则会得到重复点。
在输出的时候应该排序。
MLE和TLE:把自动机开到60005左右就能避免。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <bitset>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 6e4 + 5;
const int fir = 32, last = 126;
#define Vector vector<int>
struct Aho{
struct State{
int next[95];
int fail, cnt, number;
}state[maxn];
bool vis[maxn];
queue<int>que;
int size;
void init() {
size = 1;
while(!que.empty()) que.pop();
for(int i = 0; i < maxn; ++i) {
memset(state[i].next, 0, sizeof(state[i].next));
state[i].cnt = state[i].fail = 0;
}
}
void insert(char *S, int number) {
int n = strlen(S);
int now = 0;
for(int i = 0; i < n; ++i) {
int num = (int)S[i]-fir;
if(!state[now].next[num]) state[now].next[num] = size++;
now = state[now].next[num];
}
state[now].cnt++;
state[now].number = number;
}
void getFail() {
state[0].fail = -1;
que.push(0);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = 0; i < 95; ++i) {
if(state[u].next[i]) {
if(u == 0) state[state[u].next[i]].fail = 0;
else {
int v = state[u].fail;
while(v != -1 && !state[v].next[i]) v = state[v].fail;
state[state[u].next[i]].fail = state[v].next[i];
}
que.push(state[u].next[i]);
}
}
}
}
vector<int> Get(int u) {
vector<int> res;
while(u) {
if(!vis[u] && state[u].cnt) {
res.push_back(state[u].number);
vis[u] = true;
}
u = state[u].fail;
}
return res;
}
vector<int> match(char *S) {
memset(vis, 0, sizeof(vis));
int n = strlen(S);
int now = 0;
vector<int>res;
for(int i = 0; i < n; ++i) {
int num = S[i]-fir;
if(state[now].next[num]) now = state[now].next[num];
else {
int u = state[now].fail;
while(u != -1 && !state[u].next[num]) u = state[u].fail;
if(u == -1) now = 0;
else now = state[u].next[num];
}
if(state[now].cnt && !vis[now]) {
vector<int> temp = Get(now);
for(int i = 0; i < temp.size(); ++i) {
res.push_back(temp[i]);
}
}
}
sort(res.begin(), res.end());
return res;
}
}aho;
char S[maxn];
int main() {
int n, m;
while(scanf("%d", &n) == 1) {
getchar();
aho.init();
for(int i = 0; i < n; ++i) {
gets(S);
aho.insert(S, i+1);
}
aho.getFail();
scanf("%d", &m);
getchar();
int tol = 0;
for(int i = 0; i < m; ++i) {
gets(S);
vector<int> res = aho.match(S);
if(res.size()) {
++tol;
printf("web %d: ", i+1);
for(int j = 0; j < res.size(); ++j) {
if(j == res.size()-1) printf("%d", res[j]);
else printf("%d ", res[j]);
}
printf("\n");
}
}
printf("total: %d\n", tol);
}
return 0;
}
如有不当之处欢迎指出!