• 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;
        }
    }
  • 相关阅读:
    设计模式——装饰模式(Decorator Pattern)
    设计模式——策略模式(Strategy Pattern)
    设计模式——简单工厂模式(SimpleFactory Pattern)
    入博客园三周年记
    android+Service
    surfaceView+canvas+paint+bitmap
    Enable Sublime text 2 to support GBK in Mac
    androidstudio+opencv
    mac下的环境变量PATH
    Curl命令
  • 原文地址:https://www.cnblogs.com/jz-597/p/11145290.html
Copyright © 2020-2023  润新知