bzoj 3172: [Tjoi2013]单词 AC自动机

3172: [Tjoi2013]单词

Time Limit: 20 Sec  Memory Limit: 256 MB

题目连接

http://www.lydsy.com/JudgeOnline/problem.php?id=3172

Description

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

Input

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

Output

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

Sample Input

3
a
aa
aaa

Sample Output

6
3
1

HINT

题意

 

题解:

AC自动机,记录尾部的位置在哪儿

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)  
#define maxn 200001
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
//const int inf=0x7fffffff;   //нчоч╢С
const int inf=0x3f3f3f3f;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
//**************************************************************************************

int n,pos[maxn];
int cnt;
int next[maxn][26],sum[maxn],fail[maxn],q[maxn];
char s[maxn];
void insert(int &pos)
{
    int now=1;
    scanf("%s",s);
    int n=strlen(s);
    for(int i=0;i<n;i++)
    {
        if(!next[now][s[i]-'a'])
            next[now][s[i]-'a']=++cnt;
        now=next[now][s[i]-'a'];
        sum[now]++;
    }
    pos=now;
}
void buildfail()
{
    int head=0,tail=1;
    q[0]=1;fail[1]=0;
    while(head!=tail)
    {
        int now=q[head];
        head++;
        for(int i=0;i<26;i++)
        {
            int v=next[now][i];
            if(!v)
                continue;
            int k=fail[now];
            while(!next[k][i])
                k=fail[k];
            fail[v]=next[k][i];
            q[tail++]=v;
        }
    }
    for(int i=tail-1;i>=0;i--)
        sum[fail[q[i]]]+=sum[q[i]];
}


int main()
{
    //test;
    int n=read();
    cnt=1;
    for(int i=0;i<26;i++)
        next[0][i]=1;
    for(int i=1;i<=n;i++)
        insert(pos[i]);
    buildfail();
    for(int i=1;i<=n;i++)
        printf("%d
",sum[pos[i]]);
    return 0;
}
原文地址:https://www.cnblogs.com/qscqesze/p/4529474.html