这个题网上有很多讲解,感觉在看这个题之前最好先去看看KMP ,不然看再多的讲解,可能也不能理解构造失败指针的意义是什么。在KMP中NEXT的作用是党不匹配时指针后移,而这个后移量则是通过 NEXT 来控制的,这个题里面 构造 失败指针的意义 和NEXT的作用一样,就是前后移动指针的。这个懂了,再看看别人的图示,就会明白构造的过程,其中 我理解的是用 广度优先 遍历的。大家可以看看这个文章http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 里面讲解的很详细。
代码:
#include<stdio.h> #include<queue> using namespace std; typedef struct node { int count; node *fail; node *next[26]; }node; node *h; void insert(char *key) { int i; node *p; char *q; p=h; q=key; while(*q) { if(p->next[*q-'a']==NULL) { p->next[*q-'a']=(node*)malloc(sizeof(node)); p->next[*q-'a']->count=0; p->next[*q-'a']->fail=NULL; for(i=0;i<26;++i) p->next[*q-'a']->next[i]=NULL; } p=p->next[*q-'a']; q++; } p->count++; } void makefail() { int i; node *fa,*so,*an; queue<node*>qu; qu.push(h); while(!qu.empty()) { fa=qu.front(); qu.pop(); for(i=0;i<26;++i) if(fa->next[i]!=NULL) { if(fa==h) fa->next[i]->fail=h; else { so=fa->next[i]; an=fa->fail; while(an!=NULL&&an->next[i]==NULL) an=an->fail; if(an==NULL) so->fail=h; else so->fail=an->next[i]; } qu.push(fa->next[i]); } } } int find(char *des) { int sum=0,at,i; node *p,*q; p=h; i=0; while(des[i]) { at=des[i]-'a'; while(p->next[at]==NULL&&p!=h) p=p->fail; p=p->next[at]; if(p==NULL) p=h; q=p; while(q!=h&&q->count) { sum+=q->count; q->count=0; q=q->fail; } i++; } return sum; } int main() { int T,i,n; char str[55],des[1000005]; h=(node*)malloc(sizeof(node)); scanf("%d",&T); while(T--) { h->fail=NULL; for(i=0;i<26;++i) h->next[i]=NULL; scanf("%d",&n); while(n--) { scanf("%s",str); insert(str); } makefail(); scanf("%s",des); printf("%d\n",find(des)); } return 0; }