• bzoj 3172: [Tjoi2013]单词 AC自动机


    3172: [Tjoi2013]单词

    Time Limit: 20 Sec  Memory Limit: 256 MB

    题目连接

    http://www.lydsy.com/JudgeOnline/problem.php?id=3172

    Description

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

    Input

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

    Output

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

    Sample Input

    3
    a
    aa
    aaa

    Sample Output

    6
    3
    1

    HINT

    题意

     

    题解:

    AC自动机,记录尾部的位置在哪儿

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define test freopen("test.txt","r",stdin)  
    #define maxn 200001
    #define mod 10007
    #define eps 1e-9
    int Num;
    char CH[20];
    //const int inf=0x7fffffff;   //нчоч╢С
    const int inf=0x3f3f3f3f;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    //**************************************************************************************
    
    int n,pos[maxn];
    int cnt;
    int next[maxn][26],sum[maxn],fail[maxn],q[maxn];
    char s[maxn];
    void insert(int &pos)
    {
        int now=1;
        scanf("%s",s);
        int n=strlen(s);
        for(int i=0;i<n;i++)
        {
            if(!next[now][s[i]-'a'])
                next[now][s[i]-'a']=++cnt;
            now=next[now][s[i]-'a'];
            sum[now]++;
        }
        pos=now;
    }
    void buildfail()
    {
        int head=0,tail=1;
        q[0]=1;fail[1]=0;
        while(head!=tail)
        {
            int now=q[head];
            head++;
            for(int i=0;i<26;i++)
            {
                int v=next[now][i];
                if(!v)
                    continue;
                int k=fail[now];
                while(!next[k][i])
                    k=fail[k];
                fail[v]=next[k][i];
                q[tail++]=v;
            }
        }
        for(int i=tail-1;i>=0;i--)
            sum[fail[q[i]]]+=sum[q[i]];
    }
    
    
    int main()
    {
        //test;
        int n=read();
        cnt=1;
        for(int i=0;i<26;i++)
            next[0][i]=1;
        for(int i=1;i<=n;i++)
            insert(pos[i]);
        buildfail();
        for(int i=1;i<=n;i++)
            printf("%d
    ",sum[pos[i]]);
        return 0;
    }
  • 相关阅读:
    51nod 1412 AVL树的种类
    bzoj1093 [ZJOI2007]最大半联通子图 缩点 + 拓扑序
    bzoj1116 [POI2008]CLO 边双联通分量
    luoguP4366 [Code+#4]最短路 最短路
    51nod1821 最优集合 贪心
    51nod2000 四边形分割平面 规律题
    luoguP3250 [HNOI2016]网络 树链剖分 + 堆
    [Luogu5162]WD与积木(多项式求逆)
    [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)
    [Luogu5106]dkw的lcm
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4529474.html
Copyright © 2020-2023  润新知