zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    zip压缩类
    sqlserver配置允许快照隔离
    (三)装饰模式
    (二)策略模式
    (一)简单工厂模式
    MFC中lib和dll的区别
    VC MFC工具栏(CToolBar)控件(非常重要)
    CMFCMenuBar和CMFCToolBar相同ID,在显示不同标签文字
    CImageList类Create函数参数解析
    c++连接数据库代码
  • 原文地址:https://www.cnblogs.com/cytus/p/9457605.html
Copyright © 2011-2022 走看看