• AC自动机


    我觉得AC自动机的难点和核心是构建失败指针,父亲的失败指针的儿子(son2)中有和儿子(son1)相同的,即为son1的失败指针

    这里写图片描述

    还是有个不懂的地方:第90行,跪求大佬赐教

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<queue>
    using namespace std;
    struct Tree{
        int nxt[26];
        int count;
        int fail;
        void init()
        {
            memset(nxt,-1,sizeof(nxt));
            int fail=0;
            int count=0;
        } 
    }s[500009];
    char str[100009],des[100009];
    int n,sind=1,stu[500009];
    void ins()//构建询问串trie树 
    {
        int len=strlen(str);
        int i,j,ind=0;
        for(i=0;i<len;i++)
        {
            j=str[i]-'a';
            if(s[ind].nxt[j]==-1)
            {
                s[sind].init();
                s[ind].nxt[j]=sind;
                sind++;
            }
            ind=s[ind].nxt[j];
        }
        s[ind].count++;//增加离根节点这条路径上字符串的个数,一条路上可能不止一个单词  
    }
    void make_fail()
    {
        int qh=0,qt=0,ind,ind_f;
        for(int i=0;i<26;i++)
        {
            if(s[0].nxt[i]!=-1)
              stu[++qt]=s[0].nxt[i];//先把根下面链接的点入队 
        }
        while(qh<qt)
        {
            ind=stu[++qh];
            for(int i=0;i<26;i++)
            {
                if(s[ind].nxt[i]!=-1)//如果有 i ,求 i 的fail指针 
                {
                    stu[++qt]=s[ind].nxt[i];//入队 
                    ind_f=s[ind].fail;//父亲的失败指针 
                    int son=s[ind].nxt[i];
    
                    while(ind_f>0&&s[ind_f].nxt[i]==-1)
                      ind_f=s[ind_f].fail;//父亲失败指针的儿子中有相同的,即为son的失败指针 
    
                    if(s[ind_f].nxt[i]!=-1)
                      ind_f=s[ind_f].nxt[i];
    
                    s[son].fail=ind_f;
                }
            }
        }
    }
    int fd()
    {
        int cnt=0,i,j,len;
        int ind=0;
        len=strlen(des);
        for(i=0;i<len;i++)
        {
            j=des[i]-'a';
            while(ind>0&&s[ind].nxt[j]==-1)//一直在寻找合适的 fail 指针 ,如果是ind=0停止循环,直接判断 
             ind=s[ind].fail;
    
            if(s[ind].nxt[j]!=-1)//如果找到了成功的fail,那么开始计数 
            {
                ind=s[ind].nxt[j];
                int p=ind;
    
                while(p>0&&s[p].count!=-1)
                {
                    cnt+=s[p].count;
                    s[p].count=-1;
                    p=s[p].fail;    //ind ? p ? 跳跳跳 
                }
            }
        }
        return cnt;
    }
    int main()
    {
        s[0].init();//初始化根节点 !!! 
        scanf("%d
    ",&n);
        for(int i=1;i<=n;i++)
        {
            gets(str);
            ins();
        }
        make_fail();
    
        gets(des);
        int ans=fd();
    
        printf("%d",ans);
        return 0; 
    } 
  • 相关阅读:
    大数据产品对比
    3人3天3桶水9个人9天用几桶水
    skatebroads
    手机全面屏屏占比93%以上解决方案
    POC
    公司网站 解决方案 案例
    GBT 31000-2015 社会治安综合治理基础数据规范 数据项 编码
    GBT 33200-2016 社会治安综合治理 综治中心建设与管理规范 GBT 31000-2015 社会治安综合治理基础数据规范
    大数据 交警 户外广告设施管理监管系统平台高空坠物智慧社区城市城管警务
    破解爱奇艺腾讯优酷会员限制
  • 原文地址:https://www.cnblogs.com/dfsac/p/6819729.html
Copyright © 2020-2023  润新知