ac自动机

问题 D: 单词(word)

时间限制: 1 Sec  内存限制: 512 MB

题目描述

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

输入

第一行一个整数 N, 表示有多少个单词,接下来 N 行每行一个单词。每个单词由小 写字母组成。 

输出

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

样例输入

3


a
aa
aaa

样例输出

6
3
1

提示

对于 100% 数据,N<=200, 单词总长度不超过 10^6。 对于 20% 数据,每个单词长度不超过 3。 对于 30% 数据,每个单词长度不超过 4.。 对于另 10% 数据,所有字符相同。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
template<typename T>
inline void read(T &a){
    a=0;bool b=0;char x=getchar();
    while(x<'0'||'9'<x){
        if(x=='-')b=1;
        x=getchar();
    }
    while('0'<=x&&x<='9'){
        a=(a<<1)+(a<<3)+x-'0';
        x=getchar();
    }
    if(b)a=-a;
}
char C_[50];
int TEMP;
template<typename T>
inline void write(T a){
    if(a<0){
        a=-a;
        putchar('-');
    }
    do{
        C_[++TEMP]=a%10+'0';
        a/=10;
    }while(a);
    while(TEMP)putchar(C_[TEMP--]);
}
int n;
char ch[205];

int to[1000005][27],cnt,size[1000005];
inline void insert(){
    int u=0,len=strlen(ch+1);
    for(int i=1;i<=len;i++){
        int v=ch[i]-'a';
        if(!to[u][v])to[u][v]=++cnt;
        u=to[u][v];
        }
    size[u]++;
    
    //printf("%d %d\n",u,size[u]);
}
int fail[1000005],queue[1000005],rear,front;
inline void ac_auto(){
    rear=front=0;
    for(int i=0;i<26;i++)if(to[0][i])queue[rear++]=to[0][i];
    
    while(front<rear){
        int u=queue[front++];
        for(int i=0;i<26;i++){
            int v=to[u][i];    
            if(v)queue[rear++]=v;
            
            int p=fail[u];
            while(!to[p][i] && p)p=fail[p];
            if(to[p][i])fail[v]=to[p][i];
        }
    }
}
bool vis[1000005];
inline int ac_query(){
    int u=0,ans=0;
    int len=strlen(ch+1);
    for(int i=1;i<=len;i++){
        int v=ch[i]-'a';
        
        while(!to[u][v] && u)u=fail[u];
        if(to[u][v])u=to[u][v];
        
        for(int j=u;!vis[j];j=fail[j]){
        ans+=size[j];
        vis[j]=1;
        }
    }
    printf("%d",ans);
}
int main(){
    read(n);
    for(int i=1;i<=n;i++){
        scanf("%s",ch+1);
        insert();
    }
    ac_auto();
    
    scanf("%s",ch+1);
    ac_query();
    
    return 0;
}

 




posted @ 2019-07-27 09:44  Tj1  阅读(116)  评论(0编辑  收藏  举报