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]);

    }

    }

}

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JS数组合并(5种)

    JS数组合并(5种)前言项目过程中,经常会遇到JS数组合并的情况,时常为这个纠结。这里整理一下。简单而实用的for最容易想到的莫过于for了。会变更原数组,当然也可以写成生成新数组的形式。letarr=[1,2]letarr2=[3,4]for(letiinarr2){arr.push(arr2[i])}console.log(arr)//[1,2,3,4]arr.concat(arr2)会生成新的数组。letarr=[1,2]let

    2022年6月30日
    23
  • Thinkphp3.2.3查询24小时之内的数据条件

    Thinkphp3.2.3查询24小时之内的数据条件

    2022年2月24日
    32
  • Qt多线程:使用互斥锁

    1、官方文档:QMutex类提供线程间的访问序列化。QMutex的目的是保护一个对象、数据结构或代码片段,这样每次只有一个线程可以访问它(这类似于Javasynchronized关键字)。通常最好将互斥对象与QMutexLocker一起使用,因为这样可以很容易地确保一致地执行锁定和解锁。2、官方示例:QMutexmutex;intnumber=6;v…

    2022年4月8日
    443
  • 河北对口计算机专业一分一档6,600分以上830人!河北一市中考一分一档表出炉!…

    河北对口计算机专业一分一档6,600分以上830人!河北一市中考一分一档表出炉!…出分啦!承德市2021年中考成绩公布6月30日,承德市教育考试招生信息平台公布2021年承德市中考成绩一分一档表!今年承德中考文化和体育是630分,理化实验20分,总计是650分。据一分一档表显示今年承德中考600分以上是830人2021年承德市中考成绩一分一档表除承德外河北其他地市什么时候能查分呢?有粉丝在后台问,衡水什么时候可以查分,这不,衡水市中考成绩发布时间也来啦~衡水市一、中考成绩发布时…

    2022年7月13日
    25
  • c# dllimport用法(强中台能力)

    大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功能呢?答案是肯定的,大家可以通过C#中的DllImport直接调用这些功能。

    2022年4月11日
    153

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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