AC自动机

我们知道KMP是单模式匹配,求一个串在母串中是否出现过。那么AC自动机就是求多模式匹配的算法,判断n个串是否在母串中出现过。 AC自动机要用到字典树和失败指针两个很关键的东西,下面来具体说一下要怎么构造。 字典树的构造应该是比较容易,一颗以root为根的树,每个节点下面有26个节点,分别代表了a-z的字母;同时还有根据题目需要的一些标志,如该节点是否是单词的结束节点的sum,记录节点到根的长度的length以及访问标志flag。 ![1 建立字典树的过程 struct node{ node *next\[26\]; node *fail;//失败指针 int length;//到根节点的距离 int flag;//访问次数 }; void insert(char *s) { node *p=root; int len=strlen(s); for(int i=0;i { int x=s\[i\]-'a'; if(p->next\[x\]==NULL) { newnode=(struct node*)malloc(sizeof(struct node)); for(int i=0;i<26;i++) newnode->next\[i\]=0; newnode->fail=0;newnode->length=p->length+1; p->next\[x\]=newnode; } p=p->next\[x\]; } } 2 构建失败指针 什么是失败指针?失败指针也就是匹配过程中无法匹配时,跳转到失败指针处看是否能够匹配下去。]![借鉴了一下同学的一个图片,可以很清楚的看到失败指针的用处](https://img-blog.csdn.net/20170821153425525?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzIyMjU3Nzk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 构建bfs的过程可以用队列的思想来做。 每次寻找父亲节点的指针处,判断此节点是否有该字母 void build_fail_point()//构建失败指针 { int head=0,tail=1; node *temp,*p; q[head]=root; while(head { temp=q[head++]; for(int i=0;i<=25;i++) { if(temp->next[i]) { if(temp==root) { temp->next[i]->fail=root; } else { p=temp->fail; while(p) { if(p->next[i]) { temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) temp->next[i]->fail=root; } q[tail++]=temp->next[i]; } } } } 3 检索的过程 具体的检索过程要根据题目来进行 比如说这里我们以hdu6138为例,每次检索标记处访问过的节点。 void search(char *s,int f)//标记被访问过的节点 { node *p=root; int len=strlen(s); for(int i=0;i { int x=s[i]-'a'; while(p->next[x]==NULL&&p!=root) p=p->fail; if(p->next[x]!=NULL) p=p->next[x]; node *temp=p; while(temp!=root) { temp->flag=f; temp=temp->fail; } } }

你可能感兴趣的:(AC自动机)