这个题就是问你模式串在给定串中出现的次数
这里又进一步了解了一下AC自动机的匹配原理
其实就是每次往后移一位之后 匹配所有新后缀 最后会匹配到j==0就是根节点
如果给定串中有重复的部分那么会匹配很多次(.cnt就是来判断有没有被匹配过)
如果bca被匹配过 那么 ca a 肯定也被匹配过了
这个题的坑就是多组样例
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int t,n;
queue<int>q;
const int maxn = 2000000+100;
char str[maxn];
int k = 0;
int num[maxn];
char s[1000+10][100];
int ans[1000+10];
int ans1 = 0;
struct node{
int next[27];
int fail;
int cnt;
}tree[50000+100];
void build_tree(char *str,int id,int val){
int len = strlen(str);
int j = 0;
for(int i = 0;i < len; ++i){
j = str[i]-'A';
if(tree[id].next[j]==0){
tree[id].next[j]=++k;
}
id = tree[id].next[j];
}
tree[id].cnt++;
num[id] = val;
}
void build_fail(int id){
while(!q.empty())q.pop();
for(int i =0;i<26;++i){
int j = tree[id].next[i];
if(j!=0){
q.push(j);
tree[j].fail = id;
}
}
while(!q.empty()){
int now = q.front();
q.pop();
for(int i =0;i<26;++i){
int j = tree[now].next[i];
if(!j){
tree[now].next[i] = tree[tree[now].fail].next[i];
continue;
}
tree[j].fail = tree[tree[now].fail].next[i];
q.push(j);
}
}
}
void solve(int id,char *s){
int len = strlen(s);
for(int i = 0;i<len;++i){
if(s[i]<'A'||s[i]>'Z'){
id = 0;
continue;
}
int j = tree[id].next[s[i]-'A'];
while(j){
ans[num[j]]++;
j = tree[j].fail;
}
id = tree[id].next[s[i]-'A'];
}
}
int main(){
while(scanf("%d",&n)!=EOF){
memset(tree,0,sizeof(tree));
memset(ans,0,sizeof(ans));
memset(num,0,sizeof(num));
k = 0;
for(int i =1;i<=n;++i){
scanf("%s",s[i]);
build_tree(s[i],0,i);
}
scanf("%s",str);
build_fail(0);
solve(0,str);
for(int i =1;i<=n;++i){
if(ans[i])
printf("%s: %d\n",s[i],ans[i]);
}
}
}