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

    曾经以为AC自动机是个很难的东西,但本质上,就是Trip+KMP。

    AC自动机的运用

    用多个模式串来匹配主串。

    AC自动机的步骤

    1、建立Trie

    2、求出fail指针

    什么是fail指针?
    先看张图。
    假设模式串分别为abcd,bcd,cd,d
    示意图
    其中红色的代表fail指针
    fail指针就是指向当前所表示字符串的最长后缀字符串
    这个定义不好看……看图理解。
    仔细观察会发现和KMP差不多。

    预处理fail指针时,用BFS就行了。

    3、匹配

    也是类似于KMP。
    但是要注意,假如现在匹配到Trie中的节点为t,要试着从t开始,跳到t.fail,直到跳到根。在跳的过程中统计答案。

    例题

    Keywords Search
    懒得将题目copy过来了……

    代码

    using namespace std;
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    int n;
    char str[53];
    struct Node
    {
        int c[26];
        int fail;
        int num;
    } d[500002];
    int cnt;
    int q[500002];
    char s[1000003];
    inline void init();
    inline void insert();
    inline void build();
    inline void ac();
    int ans=0;
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int T;
        cin>>T;
        while (T--)
        {
            cin>>n;
            init();
            for (int i=1;i<=n;++i)
            {
                cin>>str;
                insert();
            }
            build();
            cin>>s;
            ac();
            cout<<ans<<'
    ';
        }
        return 0;   
    } 
    inline void init()
    {
        cnt=1;
        memset(d,0,sizeof d);
        d[1].fail=1;
    }
    inline void insert()
    {
        int t=1;
        for (char *p=str;*p;++p)
        {
            int key=*p-'a';
            if (!d[t].c[key])
                d[t].c[key]=++cnt;
            t=d[t].c[key];
        }
        ++d[t].num;
    }
    inline void build()
    {
        d[1].fail=1;
        int h=-1,t=0;
        q[0]=1;
        do
        {
            ++h;
            for (int i=0;i<26;++i)
                if (d[q[h]].c[i])
                {
                    if (q[h]!=1)
                    {
                        int p=d[q[h]].fail;
                        while (p!=1)
                        {
                            if (d[p].c[i])
                                break;
                            p=d[p].fail;
                        }
                        d[d[q[h]].c[i]].fail=(d[p].c[i]?d[p].c[i]:1);
                    }   
                    else
                        d[d[q[h]].c[i]].fail=1;
                    q[++t]=d[q[h]].c[i];
                }
        }
        while (h!=t);
    }
    inline void ac()
    {
        ans=0;
        int t=1;
        for (char *ch=s;*ch;++ch)
        {
            int key=*ch-'a';
            while (t!=1 && !d[t].c[key])
                t=d[t].fail;
            if (d[t].c[key])
                t=d[t].c[key];
            for (int i=t;i!=1;i=d[i].fail)
                if (d[i].num>=0)
                {
                    ans+=d[i].num;
                    d[i].num=-1;
                }
                else
                    break;
        }
    }
  • 相关阅读:
    关于 java jdk 环境变量的配置
    Jquery ajax 参数 详解
    关于百度world 编辑器改变上传图片的保存路径图片不显示的问题
    asp.net 中日期的格式化显示的方法
    sql server数据库中 smallint, int ,bigint ,tinyint的区别与长度
    create sequence
    INSERT高级应用
    TRUNCATE TABLE
    CREATE DATABASE LINK
    bulk
  • 原文地址:https://www.cnblogs.com/jz-597/p/11145290.html
Copyright © 2011-2022 走看看