题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222
我日,写错好多小细节,还差得远呢。。。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 500010
char str[1000010],keyword[51];
int head,tail;
typedef struct node{
struct node*fail;
struct node*next[26];
bool exist;
int count;
}*trie,node;
trie root;
trie q[N];
void creat(trie &p){
p=(trie)malloc(sizeof(node));
for(int i=0;i<26;i++)
p->next[i]=NULL;
p->exist=false;
p->count=0;
p->fail=NULL; /*原来一切的根源在于root的fail没有初始化,日*/
}
void insert(trie p,char s[]){
int k=0 ;
while(s[k]!='\0'){
if(!p->next[s[k]-'a']){
trie q;
creat(q);
p->next[s[k]-'a']=q;
}
p=p->next[s[k]-'a'];
k++;
}
p->count++;
}
void build_ac(){ /*建立fail指针,BFS*/
q[tail++]=root;
while(head!=tail){
node*p=q[head++]; /*出队*/
node*temp=NULL;
for(int i=0;i<26;i++){
if(p->next[i]!=NULL){
if(p==root)
p->next[i]->fail=root; /*root下面的26的fail必指向root*/
else{
temp=p->fail;
while(temp!=NULL){
if(temp->next[i]!=NULL){
p->next[i]->fail=temp->next[i];
break; /*找到了就break*/
}
temp=temp->fail;/*如果它的fail指针下的26个都没有的话,就指向fail指针的fail再找一次,直到退到root就也能退出来了*/
}
if(temp==NULL)
p->next[i]->fail=root;
}
q[tail++]=p->next[i]; /*入队*/
}
}
}
}
int query(trie p){
int index,len,result;
result=0;
len=strlen(str);
for(int i=0;i<len;i++){ /*写成了26,找了好久*/
index=str[i]-'a';
while(p->next[index]==NULL&&p!=root) /*预测一下,下面没有了就赶紧跳到fail去。(root跳个屁啊)*/
p=p->fail;
p=p->next[index];
if(p==NULL)
p=root;
trie temp=p;
while(temp!=root&&temp->count!=-1){ /*通过fail指针看一下到目前为止的后缀串有没有单词*/
result+=temp->count;
temp->count=-1;
temp=temp->fail;
}
}
return result;
}
int main(){
int ncase,n;
scanf("%d",&ncase);
while(ncase--){
head=tail=0;
creat(root);
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",keyword);
insert(root,keyword);
}
build_ac();
scanf("%s",str);
printf("%d\n",query(root));
}
return 0;
}