• bzoj3172: [Tjoi2013]单词 ac自动机


    某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

    Input
    第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6

    Output
    输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。

    一开始写的是把所有单词和起来然后查询,结果T了 = = ,其实只需要在fail树上搞一搞即可,假设p->fail=q,那么root到q一定是root到p的子串,所以q加上root->p出现次数,也就是按build时的逆序重新按fail树统计一遍sum即可

    /**************************************************************
        Problem: 3172
        User: walfy
        Language: C++
        Result: Accepted
        Time:332 ms
        Memory:115480 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
     
    using namespace std;
     
    const double eps=1e-6;
    const int N=1000000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    char s[N];
    struct ACM{
        int root,tot;
        int Next[N][26],fail[N],sum[N],id[210];
        int newnode()
        {
            memset(Next[tot],-1,sizeof Next[tot]);
            sum[tot]=0;
            return tot++;
        }
        void init()
        {
            tot=0;
            root=newnode();
        }
        void ins(int x)
        {
            int now=root,n=strlen(s);
            for(int i=0;i<n;i++)
            {
                if(Next[now][s[i]-'a']==-1)
                    Next[now][s[i]-'a']=newnode();
                now=Next[now][s[i]-'a'];
                sum[now]++;
            }
            id[x]=now;
        }
        void build()
        {
            int qq[N],cnt=0;
            queue<int>q;
            fail[root]=root;
            for(int i=0;i<26;i++)
            {
                if(Next[root][i]==-1)Next[root][i]=root;
                else
                {
                    fail[Next[root][i]]=root;
                    q.push(Next[root][i]);
                    qq[++cnt]=Next[root][i];
                }
            }
            while(!q.empty())
            {
                int now=q.front();
                q.pop();
                for(int i=0;i<26;i++)
                {
                    if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i];
                    else
                    {
                        fail[Next[now][i]]=Next[fail[now]][i];
                        q.push(Next[now][i]);
                        qq[++cnt]=Next[now][i];
                    }
                }
            }
            for(;cnt;cnt--)sum[fail[qq[cnt]]]+=sum[qq[cnt]];
        }
        void query(int n)
        {
            for(int i=0;i<n;i++)printf("%d
    ",sum[id[i]]);
        }
    }ac;
    int main()
    {
        ac.init();
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            ac.ins(i);
        }
        ac.build();
        ac.query(n);
        return 0;
    }
    /********************
    3
    azza
    aazza
    zaazzaz
    ********************/
    
  • 相关阅读:
    思考-少写代码
    app上传 那些事儿!
    vs2010 找不到本地服务器
    如何成为一名优秀得程序员
    python成功之路,Day2-判断和循环语句
    python成功之路,Day1-发展历史
    ES6学习笔记2-字符串扩展
    ES6学习笔记1-解构赋值
    数组的方法
    ES6
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9268480.html
Copyright © 2020-2023  润新知