题目链接:https://www.luogu.org/problemnew/show/P3808
学模板可以参考这篇博客:https://blog.csdn.net/weixin_43768644/article/details/98605417
新手の代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxnode = 1e6+5;
const int sigma_size = 26;
int trie[maxnode][sigma_size],sz;
int val[maxnode];
int last[maxnode],fail[maxnode];
queue<int>que;
char s[maxnode];
void init(int x)
{
val[x] = 0;
memset(trie[x],0,sizeof trie[x]);
}
int idx(char s){return s-'a';}
void insert(char *s)
{
int u = 0;
for (int i=0;s[i];i++){
int v = idx(s[i]);
if (!trie[u][v]){
init(sz);
trie[u][v] = sz++;
}
u = trie[u][v];
}
val[u]++;
}
void getfail()
{
fail[0] = 0;
for (int c=0;c<sigma_size;c++)
if (trie[0][c]){
int u = trie[0][c];
que.push(u);
fail[u] = last[u] = 0;
}
while (!que.empty()){
int r = que.front(); que.pop();
for (int c=0;c<sigma_size;c++){
int u = trie[r][c];
if (!u){///说的就是这个地方
trie[r][c] = trie[fail[r]][c];
continue;
}
que.push(u);
int v = fail[r];
while (v && !trie[v][c]) v = fail[v];
fail[u] = trie[v][c];
last[u] = val[fail[u]]? fail[u]:last[fail[u]];
}
}
}
int cal(int j)
{
int ans = 0;
while (j){
ans += val[j];
val[j] = 0;///如果是统计匹配串出现模板串总数,而不是几种的话,这行去掉
j = last[j];
}
return ans;
}
int Find(char *s)
{
int j=0,ans=0;
for (int i=0;s[i];i++){
int c = idx(s[i]);
j = trie[j][c];
if (val[j]) ans += cal(j);
else if (last[j]) ans += cal(last[j]);
}
return ans;
}
int main()
{
int n;
sz = 1;
scanf("%d",&n);
while (n--) scanf("%s",s),insert(s);
getfail();
/*
for (int i=1;i<sz;i++)
printf("fail[%d]=%d last[%d]=%d\n",i,fail[i],i,last[i]);
*/
scanf("%s",s);
printf("%d\n",Find(s));
return 0;
}