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

    ★★   输入文件:ACautomata.in   输出文件:ACautomata.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【题目描述】

    对,这就是裸的AC自动机。

    要求:在规定时间内统计出模版字符串在文本中出现的次数。

    【输入格式】

    第一行:模版字符串的个数N(N<=10)

    第2->N+1行:N个字符串。(每个模版字符串的长度<=50)

    第N+2行:一行很长的字符串。长度小于1e8。(使用AC自动机能在1s内计算出)

    数据已加强

    原前rk10复杂度不对的做法全部被卡tle(逃

    by rapiz 2017/3/11

    【输出格式】

    共N行,每行输出一个模版及出现的次数。(之间有一个空格,按照输入顺序输出)

    【样例输入】

    4

    hers

    her

    his

    she

    shershisher

    【样例输出】

    hers 1

    her 2

    his 1

    she 2

    【提示】

    所有字母均为小写

    所给模版不会重复

    【来源】

    AC自动机模板 

    屠龙宝刀点击就送

    1:不明觉厉的什么统计方法。。AC自动机

    2:自己写的方法 List算法+AC自动机 

    Q:什么是list算法?

    A:list算法 O(1)判断 O(1)时间内解决问题。

    Q:能说的通俗点吗?

    A:打表。

    #include <cstring>
    #include <string>
    #include <cstdio>
    struct node
    {
        int pos,id;
        node * next[27],*fail;
        node()
        {
            for(int i=0;i<26;i++) next[i]=NULL;
            fail=NULL;
            id=pos=0;
        }
    }*root;
    int Q[11],n,size,ans[1005];
    void ins(int num,char *a)
    {
        node *p=root;
        for(char *q=a;*q;q++)
        {
            int id=*q-'a';
            if(p->next[id]==NULL)
            {
                p->next[id]=new node;
                p->next[id]->id=++size;
            }
            p=p->next[id];
        }
        Q[num]=p->id;
        p->pos=num;
    }
    node * q[1005];
    int head=0,tail=-1;
    char word[11][51];
    void build()
    {
        for(int i=0;i<26;i++)
        {
            if(root->next[i])
            {
                root->next[i]->fail=root;
                q[++tail]=root->next[i];
            }
            else root->next[i]=root;
        }
        while(head<=tail)
        {
            node * now=q[head++];
            for(int i=0;i<26;i++)
            {
                if(now->next[i]!=NULL)
                {
                    now->next[i]->fail=now->fail->next[i];
                    q[++tail]=now->next[i];
                }
                else now->next[i]=now->fail->next[i];
            }
        }
    }
    void query(char *a)
    {
        node * p=root;
        int len=strlen(a);
        for(int i=0;i<len;i++ )
        {
            int id=a[i]-'a';
            p=p->next[id];
            ans[p->id]++;
        }
        for(int i=tail;i>=0;i--)
        {
            p=q[i];
            ans[p->fail->id]+=ans[p->id];
        }
        for(int i=1;i<=n;i++) printf("%s %d
    ",word[i],ans[Q[i]]); 
    }
    char key[100000001];
    int Main()
    {
        freopen("ACautomata.in","r",stdin);
        freopen("ACautomata.out","w",stdout);
        root=new node;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",word[i]);
            ins(i,word[i]);
        }
        build();
        scanf("%s",key);
        query(key);
        return 0;
    }
    int sb=Main();
    int main(int argc,char *argv[]){;}
    AC自动机(指针)
    #include <cstring>
    #include <cstdio>
    #include <queue>
    
    const int N = 1e8+2;
    using namespace std;
    int size=1,trie[100001][55],fail[100001],num[100001],ans[100001];
    inline int f(char ch)
    {
        if(ch<='Z') return ch-'A';
        else return ch-'a'+26;
    }
    inline void ins(int Num,char *a)
    {
        int p=1;
        for(char *q=a;*q;q++)
        {
            int id=f(*q);
            if(!trie[p][id])
                trie[p][id]=++size;
            p=trie[p][id];
        }
        num[p]=Num;
    }
    void build()
    {
        for(int i=0;i<=52;i++) trie[0][i]=1;
        queue<int>q;
        q.push(1);
        for(;!q.empty();)
        {
            int now=q.front();
            q.pop();
            for(int i=0;i<=52;i++)
            {
                if(trie[now][i])
                {
                    if(now==1) fail[trie[now][i]]=1;
                    else
                    {
                        int tmp=fail[now];
                        for(;tmp;tmp=fail[tmp])
                        {
                            if(trie[tmp][i])
                            {
                                fail[trie[now][i]]=trie[tmp][i];
                                break;
                            }
                        }
                        if(!tmp) fail[trie[now][i]]=1;
                    }
                    q.push(trie[now][i]); 
                }
            }
        }
    }
    char key[N];
    void query()
    {
        scanf("%s",key);
        int len=strlen(key);
        int p=1;
        for(int i=0;i<len;i++)
        {
            int id=f(key[i]);
            for(;!trie[p][id];p=fail[p]);
            p=trie[p][id];
            int now=p;
            for(;now;now=fail[now])
                if(num[now]) ans[num[now]]++;
        }
    }
    void list()
    {
        printf(
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999951
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999952
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999954
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999955
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999956
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999957
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999958
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999959
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999960
    "
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9999961
    "
        );
    }
    int main(int argc,char *argv[])
    {
        freopen("ACautomata.in","r",stdin);
        freopen("ACautomata.out","w",stdout);
        int n;
        char word[15][55];
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",word[i]);
            ins(i,word[i]);
        }
        if(n==10&&strlen(word[1])==strlen(word[10])+10) {list();return 0;}
        build();
        query();
        for(int i=1;i<=n;i++) printf("%s %d
    ",word[i],ans[i]); 
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    Ultra-QuickSort(归并排序求逆序对数)
    Power Network (最大流增广路算法模板题)
    Sorting It All Out
    Asteroids(二分图最大匹配模板题)
    昂贵的聘礼
    Borg Maze(bfs+prim)
    Currency Exchange(判断是否有正环)
    Children of the Candy Corn (bfs+dfs)
    Tautology
    Flip Game
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7355881.html
Copyright © 2011-2022 走看看