endd清零很重要,因为每次访问过后,有可能以后还会访问,不清零的话会导致重复相加。
#include <iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxm = 1000005;
const int maxc = 26;
const int maxn = 1000000 + 10;
struct Trie{
int ch[maxm][maxc],num,f[maxm],last[maxm],val[maxm],cnt,endd[maxm],ans;
void init(){
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));
memset(f,0,sizeof(f));
memset(endd,0,sizeof(endd));
num = 0; cnt = 0,ans = 0;
}
int idx(char c){
int d = c - 'a';
return d;
}
void Trie_insert(char* str){
int u = 0;
int len = strlen(str);
for(int i = 0; i < len; i++){
int c = idx(str[i]);
if(!ch[u][c]){
ch[u][c] = ++num;
}
u = ch[u][c];
}
val[u] = ++cnt;
endd[u]++;
}
void dfa(){
queue<int> que;
for(int i = 0; i < maxc; i++){
if(!ch[0][i]) continue;
que.push( ch[0][i] );
}
while(!que.empty()){
int r = que.front(); que.pop();
for(int i = 0; i < maxc; i++){
if(!ch[r][i]) {ch[r][i] = ch[ f[r] ][i]; continue;} //小trick ,含义是如果失配,则跳到不失配的点 或 0 节点去
que.push(ch[r][i]);
int v = f[r];
while(v && !ch[v][i]) v = f[v];
f[ ch[r][i] ] = ch[v][i];
last[ ch[r][i] ] = val[ f[ch[r][i] ] ] ? f[ch[r][i] ] : last[ f[ ch[r][i] ] ];
}
}
}
int Trie_count(int j){
if(j ){
int v = endd[j];
endd[j] = 0;
return v + Trie_count(last[j]);
}
return 0;
}
int Trie_search(char* str){
int u = 0,cnt = 0;
for(int i = 0;str[i]; i++){ // 这个最坑爹,如果把中间条件判断改成 i < strlen( str ),每次判断是否符合条件时都会调用一次这个函数,复杂度直接变成 n2 ,会超时,另外 strlen 返回无符号整形 ,若写成strlen - 2 则有可能生成一个很大的正数,很坑总之。。。。
int c = idx( str[i] );
/*if(ch[u][c]) u = ch[u][c];
else{
int v = f[u];
while(v && !ch[v][c]) v = f[v];
u = ch[v][c];
}*/
/* if(val[u]) cnt++;
cnt += Trie_count(last[u]);*/
while(u && !ch[u][c]) u = f[u]; // 有了上面的trick,不加这句话也可以
u = ch[u][c];
if(val[u]) cnt += Trie_count(u);
else if(last[u]) cnt += Trie_count(last[u]);
}
return cnt;
}
};
Trie trie;
int main()
{
int T,d,n;
char str[maxn];
// freopen("123.txt","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d",&d);
trie.init();
for(int i = 0; i < d; i++){
scanf("%s",str);
trie.Trie_insert(str);
}
trie.dfa();
scanf("%s",str);
n = trie.Trie_search(str);
printf("%d\n",n);
}
return 0;
}