标签:ac自动机
算是模板题级别的 但还是有要注意的地方;
首先注意的是提议要求的是求串出现的次数 而不是仅仅是种类 这就不用标记出没出现过 其次是要求的串里还有其他字符,当跑到这些字符是要把p重新赋为root 其他都一样 (hdu上记得多组输入==)
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<malloc.h> #include<queue> using namespace std; struct node { node *next[26]; node *fail; int cont; int id; }*a,*b,*root; struct Node { int id; int number; }num[1010]; char word[1010][80],txt[2000010]; int mark[1100]; int keytree(char str[],int k) { struct node *p,*q; p=root; int len=strlen(str); for(int i=0;i<len;i++) { if(p->next[str[i]-‘A‘]!=NULL) { p=p->next[str[i]-‘A‘]; } else { q=(struct node*)malloc(sizeof(struct node)); memset(q,NULL,sizeof(struct node)); p->next[str[i]-‘A‘]=q; p=q; } } p->cont++; p->id=k; return 0; } int get_fail() { root->fail=NULL; a=root; queue<node*>q; q.push(a); while(!q.empty()) { b=q.front(); q.pop(); for(int i=0;i<26;i++) { if(b->next[i]!=NULL) { if(b==root) b->next[i]->fail=root; else { a=b->fail; while(a!=NULL) { if(a->next[i]!=NULL) { b->next[i]->fail=a->next[i]; break; } a=a->fail; } if(a==NULL) b->next[i]->fail=root; } q.push(b->next[i]); } } } return 0; } int find(char str[]) { int len=strlen(str); struct node *p,*q; p=root; int ii=0; for(int i=0;i<len;i++) { if(str[i]<‘A‘||str[i]>‘Z‘) { p=root; continue; } while(p->next[str[i]-‘A‘]==NULL&&p!=root) p=p->fail; p=p->next[str[i]-‘A‘]; if(p==NULL) p=root; q=p; while(q!=root) { if(q->cont>0) { if(mark[q->id]==0) { ii++; num[ii].id=q->id; num[ii].number++; mark[q->id]=ii; } else { num[mark[q->id]].number++; } } q=q->fail; } } return ii; } int cmp(Node x,Node y) { return x.id<y.id; } int clear(node *p) { for(int i=0;i<26;i++) if(p->next[i]!=NULL) clear(p->next[i]); free(p); return 0; } int main() { int n,i,j; while(~scanf("%d",&n)) { root=(struct node*)malloc(sizeof(struct node)); memset(root,NULL,sizeof(struct node)); memset(num,0,sizeof(num)); for(i=1;i<=n;i++) { scanf("%s",word[i]); keytree(word[i],i); } get_fail(); memset(mark,0,sizeof(mark)); scanf("%s",txt); int t=find(txt); sort(num+1,num+1+t,cmp); for(i=1;i<=t;i++) { printf("%s: %d\n",word[num[i].id],num[i].number); } clear(root); } return 0; }
标签:ac自动机
原文地址:http://blog.csdn.net/zxf654073270/article/details/43307713