• 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;
    }
  • 相关阅读:
    最长公共子序列和最长公共连续子序列 andrew的日志 网易博客
    Best Computer Science Interview Books JiansNet
    分享:Mitmproxy 0.9 发布,支持 SSL 的 HTTP 代理
    创业环境差,被迫“走西口”:一位台湾码农的心路历程
    STLSupport GDB Wiki
    utils C/C++的常用工具类
    题目36 ACM在线评测系统
    DRAMA QUEEN_洪晃在ilook的BLOG
    Codeblocks调试STL——gdb with python support Wanglikai91 博客园
    python urlencode 编码
  • 原文地址:https://www.cnblogs.com/cytus/p/9457605.html
Copyright © 2020-2023  润新知