洛谷P3808 【模板】AC自动机(简单版)
题目描述
给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。
输入输出格式
输入格式:
第一行一个n,表示模式串个数;
下面n行每行一个模式串;
下面一行一个文本串。
输出格式:
一个数表示答案
题解:AC自动机裸题
#include <bits/stdc++.h>
using namespace std;
int const N = 1000005;
int const M = 1000005;
struct Node{
Node *next[26];
Node *fail;
int cnt;
Node(){
memset(next,NULL,sizeof(next));
fail = NULL;
cnt = 0;
}
}*q[M],*root;
void Insert(char *s){
int n = strlen(s);
Node *now = root;
for(int i=0;i<n;i++){
int to = s[i] - 'a';
if(now->next[to] == NULL) now->next[to] = new Node();
now = now->next[to];
}
now->cnt++;
}
void Get_Fail(){
int head = 0,tail = 0;
q[head++] = root;
root->fail = NULL;
while(head != tail){
Node *tmp = q[tail++];
Node *p;
for(int i=0;i<26;i++){
if(tmp->next[i] == NULL) continue;
if(tmp == root) tmp->next[i]->fail = root;
else{
p = tmp->fail;
while(p){
if(p->next[i]){
tmp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if(p == NULL) tmp->next[i]->fail = root;
}
q[head++] = tmp->next[i];
}
}
}
int Match(char *str){
int len = strlen(str);
Node *p = root;
int ans = 0;
for(int i=0;i<len;i++){
int to = str[i] - 'a';
while(p && p->next[to] == NULL) p = p->fail;
if(p) p = p->next[to];
else p = root;
Node *tmp = p;
while(tmp != root){
if(tmp->cnt>=0){ //标记是否访问过
ans += tmp->cnt;
tmp->cnt = -1;
}else break;
tmp = tmp->fail;
}
}
return ans;
}
int main(){
int n;
scanf("%d",&n);
root = new Node();
while(n--){
char s[55];
scanf(" %s",s);
Insert(s);
}
char str[N];
scanf(" %s",str);
Get_Fail();
printf("%d\n",Match(str));
return 0;
}

浙公网安备 33010602011771号