只是简单的弄懂了模板,至于他的一些变化,以后补充吧!
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<queue>
using namespace std;
int coun;
class node
{
public:
int cnt;
char ch;
node* fail;
node* next[30];
node(){
cnt=0;
memset(next,NULL,sizeof(next));
}
};
void build(node *&root,char str[]){
int len=strlen(str);
node *p=root;
for(int i=0;i<len;i++){
int index=str[i]-'a';
if(p->next[index]==NULL){
node *temp=new node;
temp->ch=str[i];
if(i==len-1) temp->cnt++;
p->next[index]=temp;
}
else if(i==len-1){
p->next[index]->cnt++;
}
p=p->next[index];
}
}
int match(char str[],node *tree){
int len=strlen(str);
node *p=tree;
node *temp;
int ans=0;
for(int i=0;i<len;i++){
int index=str[i]-'a';
while(p->next[index]==NULL && p!=tree)
p=p->fail;
p=p->next[index];
if(p==NULL) p=tree;
temp=p;
while(temp!=tree && temp->cnt!=-1)
{
ans+=temp->cnt;
temp->cnt=-1;
temp=temp->fail;
}
}
return ans;
}
void failSet(node *&root){
queue<node *>q;
root->fail=NULL;
q.push(root);
while(!q.empty()){
node *temp=q.front();
q.pop();
for(int i=0;i<26;i++){
if(temp->next[i]!=NULL){
node *t=temp->fail;
int index=temp->next[i]->ch-'a';
while(t!=NULL){
if(t->next[index]!=NULL){
temp->next[i]->fail=t->next[index];
break;
}
t=t->fail;
}
if(t==NULL) temp->next[i]->fail=root;
q.push(temp->next[i]);
}
}
}
}
void pre(node *tree){
for(int i=0;i<26;i++){
if(tree->next[i]!=NULL){
printf("%c",tree->next[i]->ch);
printf(" (%c) ",tree->next[i]->fail->ch);
pre(tree->next[i]);
}
}
}
int main() {
int n,t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
node *tree=new node;
for(int i=0;i<n;i++){
char str[100];
scanf("%s",str);
build(tree,str);
}
failSet(tree);
char aim[1000005];
scanf("%s",aim);
printf("%d\n",match(aim,tree));
}
}
/*
建树过程:先p节点等于根节点,寻找p节点的子节点中的ch是否与str[0]相等 如果相等,就令p为其子节点,继续寻找。
如果不能找到,就在p节点的子节点中new一个新的节点,保存其ch, 如果到达str[len-1],就标记已经导弹末尾
构造fail指针(匹配失败后指向的指针): 匹配失败找父亲的失败指向的节点,如果那个节点还是找不到儿子跟当前节点匹配,
那么继续找那个节点匹配失败的节点,直到找到或者这样的节点或者搜到了根,最后把当前节点fail指向这个节点即可。
匹配:
*/