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


    3172: [Tjoi2013]单词


    Description

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

    Input

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

    Output

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

    Sample Input

    3
    a
    aa
    aaa

    Sample Output

    6
    3
    1

    HINT

    入门

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int N=1e6+10,mod=1e9+7,inf=2e9+10;
    
    int nex[N][27],head,tail,pos[N],cnt = 1,fail[N],sum[N],q[N],n;
    char a[N];
    void insert(char *s,int &x) {
        int now = 1, len = strlen(s);
        for(int i = 0; i < len; ++i) {
            int index = s[i] - 'a';
            if(!nex[now][index]) nex[now][index] = ++cnt;
            now = nex[now][index];
            sum[now]++;
        }
        x = now;
    }
    void build_fail() {
        head = 0,tail = 0;
        q[tail++] = 1;
        fail[1] = 0;
        while(head != tail) {
            int now = q[head++];
            for(int i = 0; i < 26; ++i) {
                if(!nex[now][i]) continue;
                int p = fail[now];
                while(!nex[p][i]) p = fail[p];
                fail[nex[now][i]] = nex[p][i];
                q[tail++] = nex[now][i];
            }
        }
    }
    int main() {
        for(int i = 0; i < 26; ++i) nex[0][i] = 1;
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i) {
            scanf("%s",a);
            insert(a,pos[i]);
        }//cout<<1<<endl;
        build_fail();
        for(int i = tail-1; i >=0; --i) sum[fail[q[i]]] += sum[q[i]];
        for(int i = 1; i <= n; ++i) cout<<sum[pos[i]]<<endl;
        return 0;
    }
  • 相关阅读:
    2020.10.08 模拟赛 题解
    可爱路径 题解
    飞行路线 题解2
    架设电话线 题解
    浅谈 LCA
    浅谈 Tarjan 算法之强连通分量(危
    初赛题目整理1
    【求助,待续!】holes
    【题解】HDU4467
    【题解】zhx154嬲
  • 原文地址:https://www.cnblogs.com/zxhl/p/6527234.html
Copyright © 2020-2023  润新知