AC 自动机_模式匹配自动机

AC 自动机_模式匹配自动机学习AC自动机的前提是要会trie数和KMP字符串匹配,它的功能是能对好多个模式串进行同时查找。比如对4个模式串:hehershisshe在一条母串中:shejjjjj查找每个模式串出现的次数.我们知道KMP算法有个next数组,和KMP类似,AC自动机有一个fail指针数组,用来对整棵trie树进行滚动。AC 自动机:HUD 3065:#i

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

学习AC自动机的前提是要会trie数和KMP字符串匹配, 它的功能是能对好多个模式串进行同时查找。

比如对4个模式串:

he

hers

his

she

在一条母串中:shejjjjj 查找每个模式串出现的次数.

我们知道KMP算法有个next数组,和KMP类似,AC自动机有一个fail指针数组,用来对整棵trie树进行滚动。

AC 自动机:

HUD 3065

#include<cstdio>

#include<cstring>

#include<queue>

using namespace std;

int ch[1002*52][26],End[1002*52],cur,fail[1002*52],last[1002*52],ans[1002];

char str[2000005],str0[1002][52];

void get_fail() {

    int now,tmpFail,Next;

    queue<int> q;

    //bfs生成fail

    //初始化队列

    for(int j=0;j<26;j++) {

        if(ch[0][j]) {

            q.push(ch[0][j]);

            fail[ch[0][j]] = 0;

            last[ch[0][j]] = 0;

        }

    }

    while(!q.empty()) {

        //从队列中拿出now

        //此时now中的faillast已经算好了

        //下面计算的是ch[now][j]中的faillast

        now = q.front();q.pop();

        for(int j=0;j<26;j++) { 

            if(!ch[now][j]) continue;

            Next = ch[now][j];

            q.push(Next);

            tmpFail = fail[now];//kjkhj

            while(tmpFail&&!ch[tmpFail][j]) tmpFail = fail[tmpFail];

            fail[Next] = ch[tmpFail][j];

            last[Next] = End[fail[Next]] ? fail[Next]:last[fail[Next]];

        }

    }

}

void Find(){

    int now = 0;

    int len = strlen(str);

    for(int i=0;i<len;i++){

        if(str[i]<‘A’||str[i]>’Z’) {now=0;continue;}

        str[i]-=’A’;

        while(now&&!ch[now][str[i]]) now = fail[now];

        now = ch[now][str[i]];

        if(End[now]) ans[End[now]]++;

        int tmp = now;

//重要理解

//这时候已经滚到了节点now,下面就需要找出所有以now为结尾的模式串,就需要用到last数组了。Last数组保存的是以节点now为结尾的模式串。

//比如 abcd  bcd  两个模式串,abcdd节点的last指向bcd中的d节点。

//当然两个d节点不是同一个。

//这样就能知道当滚到abcdd节点时,我们还同时找到了bcd这个串。

//如果存在,在找到abcd的同时,我们还找到了bcd  cd  d 这三个模式串。

//事实上,下面last数组滚过的结点,在之前可能从来没有被访问过。

//《训练指南》上的代码找的是包含模式串的一段母字符串,而不是找出所有出现过的模式串。

        while(last[tmp]) {

            ans[End[last[tmp]]]++;

            tmp = last[tmp];

        }

    }

}

int main(){

    int n,now;

    while(scanf(“%d”,&n)!=EOF){

    memset(ch,0,sizeof(ch));

    memset(End,0,sizeof(End));

    memset(ans,0,sizeof(ans));

    memset(last,0,sizeof(last));

    cur = 1;

    int len;

    for(int i=1;i<=n;i++) {

        scanf(“%s”,str0[i]);

        len = strlen(str0[i]);

        now = 0;

        for(int j=0;j<len;j++) {

            str0[i][j]-=’A’;

            if(ch[now][str0[i][j]]==0) ch[now][str0[i][j]] = cur++;

            now = ch[now][str0[i][j]];

            str0[i][j]+=’A’;

        }

        End[now] = i;

    }

    get_fail();

    scanf(“%s”,str);

    Find();

    for(int i=1;i<=n;i++) {

        if(ans[i])

            printf(“%s: %d\n”,str0[i],ans[i]);

    }

    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/223028.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Java环境及Eclipse(MyEclipse)安装[通俗易懂]

    本文旨在教会新手安装和配置jdk和java开发环境,其中编程软件用的是MyEclipse,非Eclipse,简单说一下这两个区别,一般教学用的是eclipse,MyEclispe有Eclipse的所有功能,使用方法和界面基本一致,而且之后学jsp的时候,便需要开始使用MyEclipse,所以建议大家直接使用MyEclipse即可,无需安装Eclipse。本文安装的jdk和eclipse均为64位…

  • 单片机_MFRC522射频模块使用方法(含代码)

    单片机_MFRC522射频模块使用方法(含代码)MFRC522射频模块使用方法本文只讲解MFRC522射频模块使用方法(下文简称522模块),不包含原理说明,原理下篇~一、管脚解释522模块总共有8个引脚,除去复位、GND接地、3.3V电源、NC端悬空、SCK时钟端,剩余3个引脚,起数据作用。二、连接方法这里主要使用IIC的方法,相信写过IIC的同学都很熟悉这段代码。不熟悉也没关系,后文会附上52单片机的LCD1602显示UID的实现代码,包含UART测试代码。显而易见,通过总线办法读取数据只需要依照手册写代码就可以读出来,这里官方提供了

  • c#byte数组转换成字符串_字符串数组怎么定义

    c#byte数组转换成字符串_字符串数组怎么定义将一个包含ASCII编码字符的Byte数组转化为一个完整的String,可以使用如下的方法:usingSystem;usingSystem.Text;publicstaticstringFromASCIIByteArray(byte[]characters){ASCIIEncodingencoding=newASCIIEncoding();

  • python报错invalid syntax_fatal python error

    python报错invalid syntax_fatal python error因为Pycharm最近老是弹出RELPCOMMUNICATIONS,非常影响代码运行的效率。REPL(Read-Eval-PrintLoop),翻译过来就是“读取-求值-输出”循环,是一个简单的交互式的编程环境。听起来似乎挺有用,所以想直接在Pycharm中pip这个REPL。结果报错:ERROR:Commanderroredoutwithexitstatus1:…

  • 【sshd】sshd_config 中 PermitRootLogin 的forced-commands-only的限定密钥登陆、限定执行命令

    【sshd】sshd_config 中 PermitRootLogin 的forced-commands-only的限定密钥登陆、限定执行命令主讲:PermitRootLogin的可选项众所周知,sshd_config是sshd的配置文件,其中PermitRootLogin可以限定root用户通过ssh的登录方式,如禁止登陆、禁止密码登录、仅允许密钥登陆和开放登陆,以下是对可选项的概括:参数类别 是否允许ssh登陆 登录方式 交互shell yes 允许 没有限制 没有限制 without-password 允许 除密码以外 没有限制 forced-commands-on

  • mysql 前缀索引 语法_MySQL 前缀索引

    mysql 前缀索引 语法_MySQL 前缀索引索引前缀使用字符串列的索引规范中的语法,您可以创建仅使用列首字符的索引。以这种方式仅索引列值的前缀可以使索引文件小得多。为a或column编制索引时,必须为索引指定前缀长度。例如:col_name(N)NBLOBTEXTCREATETABLEtest(blob_colBLOB,INDEX(blob_col(10)));前缀最长可以为1000个字节(InnoDB表中为767…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号