AC自动机模板(luoguP3808 【模板】AC自动机(简单版))
题目背景
这是一道简单的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; }