天天看点

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;
}