题意:给定n个模式串和一个文本串,问有多少模式串出现在文本中。
思路:AC自动机模板题。原谅我也是初学,可能也无法讲清楚AC自动机的思想。大家可以去参考大牛们博客的讲解,并附上AC自动机讲解视频AC自动机
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 = 1000000+5;
const int Tot = 500000+5;
struct Aho{
struct state{
int next[26];
int fail, cnt;
}stateTable[Tot];
queue<int>que;
//size表示当前节点是第几个节点
int size;
void init() {
while(!que.empty()) que.pop();
for(int i = 0; i < Tot; ++i) {
memset(stateTable[i].next, 0, sizeof(stateTable[i].next));
stateTable[i].fail = stateTable[i].cnt = 0;
}
size = 1;
}
//在字典树中插入S
void insert(char *S){
int n = strlen(S);
int now = 0;
for(int i = 0; i < n; ++i) {
char c = S[i];
if(!stateTable[now].next[c-'a']) {
stateTable[now].next[c-'a'] = size++;
}
//向下走
now = stateTable[now].next[c-'a'];
}
stateTable[now].cnt++;
}
void build() {
stateTable[0].fail = -1;
que.push(0);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = 0; i < 26; ++i) {
if(stateTable[u].next[i]) {
//处理节点u下面第i个节点失配的情况
if(u == 0) stateTable[stateTable[u].next[i]].fail = 0;
else {
int v = stateTable[u].fail;
while(v != -1) {
if(stateTable[v].next[i]) {
stateTable[stateTable[u].next[i]].fail = stateTable[v].next[i];
break;
}
v = stateTable[v].fail;
}
if(v == -1) stateTable[stateTable[u].next[i]].fail = 0;
}
que.push(stateTable[u].next[i]);
}
}
}
}
int Get(int u) {
int res = 0;
while(u) {
res += stateTable[u].cnt;
stateTable[u].cnt = 0;
u = stateTable[u].fail;
}
return res;
}
int match(char *S) {
int n= strlen(S);
int res = 0, now = 0;
for(int i = 0; i < n; ++i) {
char c = S[i];
if(stateTable[now].next[c-'a'])
now = stateTable[now].next[c-'a'];
else {
int p = stateTable[now].fail;
while(p != -1 && !stateTable[p].next[c-'a']) p = stateTable[p].fail;
if(p == -1) now = 0;
else now = stateTable[p].next[c-'a'];
}
if(stateTable[now].cnt)
res += Get(now);
}
return res;
}
}aho;
char S[maxn];
int main() {
int T, n;
scanf("%d", &T);
while(T--) {
aho.init();
scanf("%d", &n);
for(int i = 0; i < n; ++i) {
scanf("%s", S);
aho.insert(S);
}
aho.build();
scanf("%s", S);
printf("%d\n", aho.match(S));
}
return 0;
}
如有不当之处欢迎指出!