贴份模板
胡大神和崔大神的组合模板
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 1000010
#define LL long long
#define INF 0xfffffff
#define maxch 26
const double eps = 1e-;
const double pi = acos(-1.0);
const double inf = ~0u>>;
const int child_num = ;
char ss[N];
class ACAutomation
{
private:
int ch[N][maxch];
int val[N];
int fail[N];
int Q[N];
int id[];
int sz;
// int dp[2][N][1<<10];
public:
void init()
{
fail[] = ;
for(int i = ; i < child_num; i++)
id[i+'a'] = i;
}
void reset()//初始化
{
memset(ch[],,sizeof(ch[]));
memset(val,,sizeof(val));
sz = ;
}
void insert(char *a,int key)//建立trie树
{
int p = ;
for( ; *a ; a++)
{
int c = id[*a];
if(ch[p][c]==)
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[p][c] = sz++;
}
p = ch[p][c];
}
val[p] += key;
}
void construct()//构建fail指针
{
int head = ,tail = ,i;
for(i = ;i < child_num ; i++)
{
if(ch[][i])
{
fail[ch[][i]] = ;
Q[tail++] = ch[][i];
}
}
while(head!=tail)
{
int u = Q[head++];
for(i = ;i < child_num ;i ++)
{
if(ch[u][i]!=)
{
Q[tail++] = ch[u][i];
fail[ch[u][i]] = ch[fail[u]][i];
}
else
ch[u][i] = ch[fail[u]][i];
}
}
}
int work(char *s)
{
int k = strlen(s);
int p = ,ans = ;
for(int i = ; i < k ; i++)
{
int d = s[i]-'a';
p = ch[p][d];
int tmp = p;
while(tmp!=&&val[tmp]!=)
{
ans+=val[tmp];
val[tmp] = ;
tmp = fail[tmp];
}
}
return ans;
} }ac;
int main()
{
int t,n;
char word[];
ac.init();
cin>>t;
while(t--)
{
cin>>n;
ac.reset();
while(n--)
{
scanf("%s",word);
ac.insert(word,);
}
ac.construct();
scanf("%s",ss);
printf("%d\n",ac.work(ss));
}
return ;
}