32.3-4AC自动机
2016-04-14 21:38
218 查看
不知道这是不是题目说的自动机…不过AC自动机还是很有必要了解的
自动机…确实像一个机器,它的状态是有限的,会根据当前的状态和输入转换到另一种状态…原谅我不禁想起了高中生物书上的核糖体做氨基酸链的过程…其实还是有一点像的对吧~~
学习AC自动机算法,首先应该看看32.3和32.4节(两节都非常有启示性),总而言之,这个算法几乎就是两者的混合
欲要详细的解说:请看
AC自动机算法简单介绍(看了之前书上那两节再看这个基本就可以写出代码了)
和
HDU 3901 Wildcard AC自动机通配符匹配(这个主要是那张图很好)
自动机…确实像一个机器,它的状态是有限的,会根据当前的状态和输入转换到另一种状态…原谅我不禁想起了高中生物书上的核糖体做氨基酸链的过程…其实还是有一点像的对吧~~
学习AC自动机算法,首先应该看看32.3和32.4节(两节都非常有启示性),总而言之,这个算法几乎就是两者的混合
欲要详细的解说:请看
AC自动机算法简单介绍(看了之前书上那两节再看这个基本就可以写出代码了)
和
HDU 3901 Wildcard AC自动机通配符匹配(这个主要是那张图很好)
样例输入: asataabandabybatbabyasbabe 7 an at as ant and baby babe
#include<stdio.h> #include<stdlib.h> #include<string.h> #define maxn 1000 #define maxm 100 typedef struct node{ int ok;/*节点对应的模式串编号*/ struct node *p,*s[26],*fail;/*p为父节点指针,s为子节点指针数组,限制为小写字母,fail为跳转指针,相当于π函数*/ }node; typedef struct AC{ int n;/*模式串个数*/ node *root;/*trie树根,相当于KMP算法中的0(长度为0,也就是空串)*/ char p[maxn][maxm];/*模式串*/ }AC; node *newnode(void) { node *New; New=(node *)malloc(sizeof(node)); New->ok=-1;/*初始化节点不代表任何模式串*/ New->p=NULL; New->fail=NULL; int i; for (i=0;i<26;i++) New->s[i]=NULL; return New; } int *insert(node *root,char p[],int i) { int m=strlen(p),k; node *now=root; for (k=0;k<m;k++) { int idx=(int)(p[k]-'a');/*p[k]对应的s数组下标,下同*/ if (!now->s[idx])/*如果s[idx]是NULL,说明now后面没有p[k]这个字母*/ { node *New=newnode(); New->p=now; now->s[idx]=New; } now=now->s[idx]; } now->ok=i;/*保存模式串的编号,此时now是p中最后一个字母的位置*/ return 0; } int computfail(AC ac)/*计算π函数,和KMP算法很相似*/ { int i,n=ac.n; char (*p)[maxm]=ac.p;/*为了方便,令p=ac.p,这是数组指针*/ node *root=ac.root; for (i=0;i<n;i++)/*相当于对每个模式串运行一次comput_prefix_function,只是KMP中π是数字的形式,这里是指针*/ { int k,idx; node *now; now=root; idx=(int)(p[i][0]-'a'); now->s[idx]->fail=root;/*相当于令π[1]=0*/ now=now->s[idx];/*相当于KMP中的q*/ node *pre=root;/*相当于KMP中的k,即π[q-1]*/ for (k=1;k<strlen(p[i]);k++)/*for q=2 to m*//*k(字符串下标,和now是等同的,也和KMP中的q是等同的(由于字符串从0开始,相差1))*/ { idx=(int)(p[i][k]-'a'); now=now->s[idx]; while (pre!=root&&pre->s[idx]==NULL)/*while (k>0&&p[k+1]!=p[q])*/ pre=pre->fail;/*k=π(k)*/ if (pre->s[idx])/*if (p[k+1]==p[q])*/ pre=pre->s[idx];/*k++*/ now->fail=pre;/*π[q]=k*/ } } return 0; } int match(AC ac,char t[]) { int m=strlen(t),i; node *root=ac.root; node *pre=root;/*q=0*/ for (i=0;i<m;i++) { int idx=(int)(t[i]-'a'); while (pre!=root&&pre->s[idx]==NULL) pre=pre->fail; if (pre->s[idx]) pre=pre->s[idx];/*上面的注释同computfail*/ if (pre->ok!=-1) printf("%s: %d\n",ac.p[pre->ok],i-strlen(ac.p[pre->ok])+1);/*输出匹配的模式串和对应的起始位置(从0开始)*/ /*这里和书上的KMP算法略有不同,书上令q=π[q]是为了避免下次匹配时第6行数组越界,但是这里不存在这个问题,因为只需要判断节点某孩子的指针是否为空就可以断定两个字符是否匹配,相反,如果这里采取和书上一样的措施,结果可能有错,因为模式串中可能存在前缀包含,比如an和and,匹配完了an将不能匹配到and*/ } return 0; } AC initac(void) { AC ac; int n,i; scanf("%d",&n); ac.n=n; ac.root=newnode(); ac.root->p=ac.root; ac.root->fail=ac.root; for (i=0;i<n;i++) { scanf("%s",ac.p[i]); insert(ac.root,ac.p[i],i); } return ac; } int main(void) { char t[maxn]; scanf("%s",t); AC ac; ac=initac(); computfail(ac); match(ac,t); return 0; }
相关文章推荐
- 进一步封装highchart,打造自己的图表插件:jHighChart.js
- 【Android】Android中期项目设计题目-界面设计小作业
- aspcms网站访问出现3706错误, 错误描述:未找到提供程序。该程序可能未正确安装,解决的方法。
- C语言-郝斌笔记-001求二次方程的根
- 在 IIS 上创建 FTP 站点
- HttpServletResponse详解
- Android获得当前前台运行的app包名
- ToDo-List-><学习Python>
- PE文件的执行顺序
- dreamwear怎么制作二级列表
- Dubbo高级篇_09_Dubbo负载均衡策略
- java中的内省(Introspector)
- Android论如何写一个正确的单例模式
- kohana中模板以及视图中数据传送
- linux系统时间同步,硬件时钟和系统时间同步,时区的设置
- 作业调度模拟程序
- 共享内存的实现
- PAT (Basic Level) Practise (中文)1023. 组个最小数 (20)
- 浅谈AlphaGo背后所涉及的深度学习技术
- js解析json时遇到英文单双引号