在root上接一个super可以使操作变得简便
注意及时将match清零
#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <queue>
#define N 1000000
using namespace std;
typedef long long ll;
int n,t;
char s1[50],s2[1000000];
struct Node{
Node* ch[26],*fail;
int match;
void clear(){
memset(this,0,sizeof(Node));
}
};
Node a[N],*root,*super,*cur;//super用来简便操作,使root能够拥有fail(super)
Node* newNode(){
cur->clear();
return cur++;
}
void clear(){
cur = a;
super = newNode();
root = newNode();
root->fail = super;
for(int i=0;i<26;i++){
super->ch[i] = root;//root的fail的所有子节点都是root
}
super->match = -1;
}
void build(){
Node *t;
queue<Node*>que;
que.push(root);
while (!que.empty())
{
t = que.front();que.pop();
for(int i=0;i<26;i++){
if(t->ch[i]){
t->ch[i]->fail = t->fail->ch[i];
que.push(t->ch[i]);
}else{
t->ch[i] = t->fail->ch[i];
}
}
}
}
void insert(char s[]){
Node *t = root;
while (*s != '\0')
{
int x = *s-'a';
if(t->ch[x] == NULL){
t->ch[x] = newNode();
}
t = t->ch[x];
s++;
}
t->match++;
}
int run(char s[]){
int ans = 0;
Node* t = root;
for(;*s;s++){
int x = *s-'a';
t = t->ch[x];
for(Node* u = t;u->match != -1;u = u->fail){//match!=-1,即为找到super或者曾经计数过的点
ans+=u->match;
u->match = -1;//避免重复计数
}
}
return ans;
}
int main(){
int i,j,x,y;
scanf("%d",&t);
while (t--)
{
clear();
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",s1);
insert(s1);
}
build();
scanf("%s",s2);
printf("%d\n",run(s2));
}
return 0;
}