• Evanyou Blog 彩带


      题目传送门

    单词

    题目描述

    小张最近在忙毕设,所以一直在读论文。一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次。

    输入输出格式

    输入格式:

     

    第一行一个整数N,表示有N个单词。接下来N行每行一个单词,每个单词都由小写字母(a-z)组成。(N≤200)

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 
    3
    a
    aa
    aaa
    输出样例#1: 
    6
    3
    1
    

    说明

    数据范围

    30%的数据, 单词总长度不超过10^3

    100%的数据,单词总长度不超过10^6


      分析:

      此题有多种做法,$hash$(太麻烦不想打),后缀数组(不会),$AC$自动机(就是你了)。为了复习一波$AC$自动机,蒟蒻选择了此种做法。

      实际上也算是比较明显的$AC$自动机了,在做的时候记录路径就可以轻松过了,思路就不多赘述,蒟蒻就只放代码了。

      Code:

    //It is made by HolseLee on 10th Aug 2018
    //Luogu.org P3966
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=202;
    const int L=1e6+7;
    int n,ans[N],t[L][26],tot,all,val[L],fail[L],lis[L],mk[L];
    char s[L+N],a[L];
    queue<int>T;
    
    struct Trie{
        void ins(int num)
        {
            int len=strlen(a),root=0,v;
            for(int i=0;i<len;++i){
                s[all++]=a[i];
            }
            s[all++]='#';
            for(int i=0;i<len;++i){
                v=a[i]-'a';
                if(!t[root][v])t[root][v]=++tot;
                root=t[root][v];
            }
            if(!val[root])val[root]=num;
            mk[num]=val[root];
        }
    
        void build()
        {
            int u=0,v;
            for(int i=0;i<26;++i){
                if(t[u][i])T.push(t[u][i]);
            }
            while(!T.empty()){
                u=T.front();T.pop();
                for(int i=0;i<26;++i){
                    v=t[u][i];
                    if(v){
                        fail[v]=t[fail[u]][i];
                        lis[v]=val[fail[v]]?fail[v]:lis[fail[v]];
                        T.push(v);
                    }
                    else t[u][i]=t[fail[u]][i];
                }
            }
        }
        
        void quary()
        {
            int u=0,v;
            for(int i=0;i<all;++i){
                if(s[i]=='#'){
                    u=0;continue;
                }
                u=t[u][s[i]-'a'];
                if(val[u])ans[val[u]]++;
                v=lis[u];
                while(v){
                    ans[val[v]]++;
                    v=lis[v];
                }
            }
        }
    }ac;
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%s",a);
            ac.ins(i);
        }
        ac.build();ac.quary();
        for(int i=1;i<=n;++i)
        printf("%d
    ",ans[mk[i]]);
        return 0;
    }
  • 相关阅读:
    22、编译安装nginx及性能优化
    21、nginx之ngx_http_proxy_module模块
    20、nginx之ngx_http_upstream_module模块
    19、修改文件描述符
    8、负载均衡HAproxy部署
    6、负载均衡HAproxy介绍
    17、ansible配置管理
    18、通过yum命令只下载rpm包不安装
    16、编译安装ansible
    python余弦相似度
  • 原文地址:https://www.cnblogs.com/cytus/p/9457605.html
Copyright © 2020-2023  润新知