• 单词 (AC自动机)


    题目描述

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

    输入描述:

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

    输出描述:

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

    示例1

    输入

    3

    a

    aa

    aaa

    输出

    6

    3

    1

    题解

    AC自动机概念题,考的对 fail指针的理解,就是建树bfs这里就体现了AC自动机手写队列的好处,省了一次bfs

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6 + 5;
    const int M = 26;
    const int C = 'a';
    
    struct AC
    {
        int tr[maxn][M], cnt[maxn], fail[maxn], endpos[maxn]; 
        int q[maxn], tot, head, tail; 
        
        void insert(char *s, int id)
        {
            int p = 0;
            for (int i = 0; s[i]; ++i)
            {
                int ch = s[i] - C;
                if (tr[p][ch] == 0) tr[p][ch] = ++tot;
                p = tr[p][ch], ++cnt[p];
            }
            endpos[id] = p; 
        }
        
        void build()
        {
            head = 0, tail = -1;
            for (int i = 0; i < M; ++i)
                if (tr[0][i]) q[++tail] = tr[0][i];
            while (head <= tail)
            {
                int p = q[head++];
                for (int i = 0; i < M; ++i)
                    if (tr[p][i]) 
                        fail[tr[p][i]] = tr[fail[p]][i], q[++tail] = tr[p][i];
                    else tr[p][i] = tr[fail[p]][i];  
            }
        }
    }ac;
    
    int n;
    char s[maxn];
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
            scanf("%s", s), ac.insert(s, i);
        ac.build();
        for (int i = ac.tail; i >= 0; --i)//省去了bfs
            ac.cnt[ac.fail[ac.q[i]]] += ac.cnt[ac.q[i]];
        for (int i = 1; i <= n; ++i)
            printf("%d
    ", ac.cnt[ac.endpos[i]]);
        return 0;
    }
  • 相关阅读:
    CSS 去掉文字选中状态
    解决MAC系统升级导致COCOAPODS失效问题
    qr-mili Tekniskt stöd
    JavaScript 随笔
    Https 单向验证 双向验证
    git 常用指令
    h5或者微信端吊起app
    创建本地服务器环境
    jenkins 关闭和重启的实现
    jenkins 忘记用户名和密码
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12692682.html
Copyright © 2020-2023  润新知