题目背景
这是一道简单的AC自动机模板题。
用于检测正确性以及算法常数。
为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。
管理员提示:本题数据内有重复的单词,且重复单词应该计算多次,请各位注意
题目描述
给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。
输入输出格式
输入格式:
第一行一个n,表示模式串个数;
下面n行每行一个模式串;
下面一行一个文本串。
输出格式:
一个数表示答案
输入输出样例
说明
subtask1[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6,n=1;
subtask2[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6;
%:pragma GCC optimize(2)
;
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;
const int N = 1e6 + 10;
int cnt, nxt[N][30], fail[N], tot[N], ans, n;
char s[N];
queue<int> q;
void insert() {
scanf("%s", s);
int x = 0;
for(int i = 0 ; s[i] ; ++ i) {
int c = s[i] - 'a';
if(!nxt[x][c]) nxt[x][c] = ++ cnt;
x = nxt[x][c];
}
++ tot[x];
}
void bfs() {
for(int i = 0 ; i < 26 ; ++ i) {
if(nxt[0][i]) {
fail[nxt[0][i]] = 0;
q.push(nxt[0][i]);
}
}
while(q.size()) {
int u = q.front(); q.pop();
for(int i = 0 ; i < 26 ; ++ i) {
int v = nxt[u][i];
if(!v) nxt[u][i] = nxt[fail[u]][i];
else {
fail[v] = nxt[fail[u]][i];
q.push(v);
}
}
}
}
void sol() {
scanf("%s", s);
int u = 1;
for(int i = 0 ; s[i] ; ++ i) {
u = nxt[u][s[i] - 'a'];
int v = u;
while(v && ~tot[v]) {
ans += tot[v];
tot[v] = -1;
v = fail[v];
}
}
}
int main() {
scanf("%d", &n);
for(int i = 1 ; i <= n ; ++ i) {
insert();
}
bfs();
sol();
printf("%d\n", ans);
return 0;
}