HDU2222-tire,AC自动机
来源:互联网 发布:龙腾世纪3 捏脸数据 编辑:程序博客网 时间:2024/05/16 16:59
好吧!为了以后复习,也为了与大家分享!我把书上的简介打到这里.
基本概念:
AC自动机是一种特殊的自动机,是通过在tires树上添加一些额外的边组成,其核心部分是后缀节点的构建。
算法:
AC自动机的构建分两步,首先通过所有的模式串建立起tire树,然后从树根向下一次计算每个节点的后缀节点。
AC自动机后缀的建立过程和kmp算法中next数组的求解过程十分相似,这里我们也用next数组来表示节点i对应的后节点的标号,fa[i]表示节点i在tire树上的父节点,此外假设
从fa[i]到i的那条边上的字符是c。其核心思想是首先看next[fa[i]]是否有条字符同样为c边,如果是,则next[i]即为next[fa[i]]标着c的那条边所指向的子节点。否则继续
检测next[next[fa[i]]]节点。如果通过不停的next还是无法找到满足条件的节点,则表示tire上没有串与节点i的路径字符串某个字符串后缀相同,那么其后缀
节点就为根,
寻找next的伪代码:
将root压人列队
next[root]<- (-1);
while(列队非空){
x<-弹出队首。
for(x标记为c的儿子i){
tmp<-next[x]
while(tmp!=-1且tmp不含有标记为c的儿子) tmp<-next[tmp];
if(tmp=-1) next[i]<-root;
else next[i]<-tmp的标记为c的边指向的节点。
将i压入队列
}
}
AC自动机的遍历和tire数很相似,对于主串s其遍历大概如下:
(1) 从根节点开始,从前向后一次查看s的每个字符c。
(2)如果当前节点x含有标记为c的边,沿着边走到下个节点。
(3) 否则,查看x的后缀节点next[x]。
如果next[x]含有标记为c的边,那么就沿着这条边走到next[x]的标记为c的那条边所指向的节点。
如果next[x]也没含有标记为c的边,继续查看next[x]的后缀节点next[next[x]],如果直到查看到根节点还无法找到满足条件的节点。那么就移动根节点。
(4) 如果还有字符,回到(2)。
为了理解看这张图。
写了这么多就差不多了.
HDU2222这是到AC自动机人门题。代码如下:
#include<cstdio>#include<cstring>#define Max 500001using namespace std;char st[Max*2];int head,tail;struct node{node *next[26];node *fail;int cnt;node(){cnt=0;fail=NULL;memset(next,NULL,sizeof(next));}}*Q[Max];inline void insert(node *root){node *p=root;int i=0,idx;while(st[i]){idx=st[i]-'a';if(p->next[idx]==NULL) p->next[idx]=new node;p=p->next[idx];i++;}p->cnt++;}void built(node *root){root->fail=NULL;Q[head++]=root;while(head!=tail){node* tmp=Q[tail++];node* p=NULL;for(int i=0;i<26;i++){if(tmp->next[i]!=NULL){if(tmp==root) tmp->next[i]->fail=root;else{p=tmp->fail;while(p!=NULL){if(p->next[i]!=NULL){tmp->next[i]->fail=p->next[i];break;}p=p->fail;}if(p==NULL) tmp->next[i]->fail=root;}Q[head++]=tmp->next[i];}}}}int query(node *root){int i=0,res=0,idx;node *p=root;while(st[i]){idx=st[i]-'a';while(p->next[idx]==NULL&&p!=root) p=p->fail;p=p->next[idx];p=(p==NULL)?root:p;node *tmp=p;while(tmp!=root&&tmp->cnt!=-1){res+=tmp->cnt;tmp->cnt=-1;tmp=tmp->fail;}i++;}return res;}int main(){int n,t;scanf("%d",&t);while(t--){head=tail=0;node *root=new node;scanf("%d",&n);while(n--){scanf("%s",st);insert(root);}built(root);scanf("%s",st);printf("%d\n",query(root));}return 0;}
- HDU2222-tire,AC自动机
- hdu2222 ac自动机模版
- hdu2222 AC自动机
- hdu2222,(ac自动机)
- AC自动机模板 hdu2222
- hdu2222-AC自动机
- HDU2222 AC自动机
- hdu2222 AC自动机
- 【AC自动机】HDU2222
- hdu2222 AC自动机
- hdu2222 ac自动机。。。。
- HDU2222 AC自动机入门
- hdu2222 ac自动机模板
- hdu2222 AC自动机
- 初识AC自动机 HDU2222
- hdu2222(AC自动机入门)
- AC自动机 hdu2222
- HDU2222 AC自动机模板
- android.mk
- SQL提高查询效率(1)
- Hoj 3149 The median number problem2
- Ubuntu 12.04常用的快捷键
- Android获取SD卡上的APK文件,并且判断是否安装过、是否可以更新到新版本的工具类
- HDU2222-tire,AC自动机
- Unity3D 给NGUI自带的控件添加新属性
- 第二课 oracle中的用户,角色,权限
- Surrounded Regions
- Windows程序设计_Chap03_窗口与消息_学习笔记
- (整理)BT5 R3安装中文语言包(解决半中文半英文)
- iOS Safari和UIWebView对orientationchange事件的实现
- struts1 的tag <logic:equal >的原理及bug
- Linux 内核详解以及内核缓冲区技术