1. 程式人生 > >AC自動機 [模板]

AC自動機 [模板]

傳送門

#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
#include<iostream>
#define N 500050
using namespace std;
int fail[N],ch[N][26],cnt[N];
int T,n,tot=1;
void Init(){
	memset(fail,0,sizeof(fail));
	memset(ch,0,sizeof(ch));
	memset(cnt,0,sizeof(cnt)); tot = 1;
}
void Insert(string s){
	int len = s.length(); int now = 1;
	for(int i=0;i<len;i++){
		int x = s[i] - 'a';
		if(!ch[now][x]) ch[now][x] = ++tot;
		now = ch[now][x]; 
	} cnt[now]++;
}
void build(){
	queue<int> q; q.push(1);
	while(!q.empty()){
		int x = q.front(); q.pop();
		for(int i=0;i<26;i++) if(ch[x][i]){
			if(x==1) fail[ch[x][i]] = 1;
			else{ int x1 = fail[x];
				for(; x1; x1=fail[x1]) if(ch[x1][i]){
					fail[ch[x][i]] = ch[x1][i]; break;
				} if(x1==0) fail[ch[x][i]] = 1;
			} q.push(ch[x][i]);
		}
	}
}
int quary(string s){
	int len = s.length(); int now = 1 , ans = 0;
	for(int i=0;i<len;i++){
		int x = s[i] - 'a';
		while(!ch[now][x] && now!=1) now = fail[now];
		if(ch[now][x]==0) continue; now = ch[now][x];
		for(int j=now ;j != 1 && cnt[j] != -1; j = fail[j]){
			ans += cnt[j] , cnt[j] = -1;
		}
	} return ans;
}
int main(){
	scanf("%d",&T); 
	while(T--){
		scanf("%d",&n); Init();
		for(int i=1;i<=n;i++){
			string s; cin>>s; Insert(s);
		} build();
		string s; cin>>s; printf("%d\n",quary(s));
	} return 0;
}