[TJOI2013]单词

来源:互联网 发布:拟线性偏好知乎 编辑:程序博客网 时间:2024/05/01 19:50

2755: [TJOI2013]单词

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 6  Solved: 3
[Submit][Status][Web Board]

Description

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

Input

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

Output

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

Sample Input

3aaaaaa

Sample Output

631

HINT

 

Source

 题解:
  

  求出fail树以后。。。

  对每个串的每个节点打标记

  然后输出每个串终点子树的标记个数和

#include<iostream>#include<cstring>#include<cstdio>#define maxn 1000001using namespace std;int n,tot;int sum[maxn],fai[maxn],son[maxn][27],pos[201],lis[maxn];char s[maxn];void insert(int x){    scanf("%s",s+1);    int p=0,nn=strlen(s+1);    for (int i=1; i<=nn; i++)    {        if (!son[p][s[i]-'a']) son[p][s[i]-'a']=++tot;        p=son[p][s[i]-'a'];        sum[p]++;    }    pos[x]=p;}void failed(){    int head=0,tail=1; lis[1]=0; fai[0]=-1;        int a;        while (head<tail)        {               int now=lis[++head];            for (int i=0;i<26;i++)            {                if (son[now][i])                {                    lis[++tail]=son[now][i];                    a=fai[now];                    while (a!=-1&&!son[a][i]) a=fai[a];                    if (a>=0) fai[son[now][i]]=son[a][i];                    else fai[son[now][i]]=0;                }            }        }     for (int i=tail; i>=1; i--)        sum[fai[lis[i]]]+=sum[lis[i]];}int main(){    cin>>n; tot=0;    for (int i=1; i<=n; i++) insert(i);     failed();    for (int i=1; i<=n; i++) printf("%d\n",sum[pos[i]]); }
View Code

 

0 0
原创粉丝点击