zoukankan      html  css  js  c++  java
  • AC自动机

    推荐blog

     认为上面这篇blog已经讲述的十分清楚(一定要画图多手动模拟,,才能感受AC自动机的奥妙),所以解释两个我想了很久也没想明白的问题 (是基于代码的)

    1.为什么要用BFS太蠢了QWQ

    2.连接fail时的一些特殊情况到底是怎么处理的

    例如当前有一颗这样的树:

    我们已经按照操作,搜索到了标红节点,按照AC自动机的思想连fail边,因为我们已经处理过它的父亲节点c节点的fail值,所以d节点的fail值应该等于。。讲不清了大概是这样连边:

    然而虚拟d点的编号为0,那这样红色d点岂不是相当于连到了顶点,但其实不是,我们也可以看出来d点应该连在第3列的d点上

    但这是怎么处理的呢?因为是BFS,是按照深度由浅到深进行处理的,所以虚拟点其实已经处理过且值已变成另一个d点了

    就像是这样:

    推荐题目:洛谷P3808

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    int num,ans;
    struct{
        int vis[28];
        int fail;
        int end;
    }a[1000006];
    void build(string s){
        int i,l,now=0;
        l=s.length();
        for(i=0;i<l;i++){
            if(a[now].vis[s[i]-'a']==0){
                num++;
                a[now].vis[s[i]-'a']=num;
            }
            now=a[now].vis[s[i]-'a'];
        }
        a[now].end++;
    }
    void fail(){
        queue<int>q;
        int now,i;
        for(int i=0;i<26;++i){
              if(a[0].vis[i]!=0)
                  q.push(a[0].vis[i]);
        }//一定要有,若只是将0放入队列中,那第一层字母将会指向它自己,然而它应该指向0点
        while(!q.empty()){
            now=q.front();q.pop();
            for(i=0;i<26;i++){
                if(a[now].vis[i]){
                    a[a[now].vis[i]].fail=a[a[now].fail].vis[i];
                    q.push(a[now].vis[i]);
                }
                else a[now].vis[i]=a[a[now].fail].vis[i];
            }
        }
    }
    void find(string s){
        int i,l,now,j;
        l=s.length();
        now=0;
        for(i=0;i<l;i++){
                now=a[now].vis[s[i]-'a'];
                for(j=now;j&&a[j].end!=-1;j=a[j].fail){
                    ans+=a[j].end;
                    a[j].end=-1;
                }
        }
    }
    int main(){
        int i,j,l,n;
        string s;
        cin>>n;
        for(i=1;i<=n;i++){
            cin>>s;
            build(s);
        }
        fail();
        //for(i=1;i<=num;i++)printf("%d %d ",a[i].fail,a[i].end);
        cin>>s;
        find(s);
        printf("%d",ans);
    }
  • 相关阅读:
    关于 haproxy keepalived的测试
    关于 tornado.simple_httpclient SimpleAsyncHTTPClient fetch下载大文件,默认60s的问题
    Linux系统性能监控工具介绍之-tsar
    linux 系统监控好文
    python中字符串使用需要注意的地方
    如何搭建一个GitHub在自己的服务器上?
    linux使用FIO测试磁盘的iops
    适合编程学习的网站
    linux swap的添加等等
    redis主从复制原理与优化
  • 原文地址:https://www.cnblogs.com/Jessica-Cao/p/13551841.html
Copyright © 2011-2022 走看看