bzoj 3172: [Tjoi2013]单词

3172: [Tjoi2013]单词

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 2577   Solved: 1205
[ Submit][ Status][ Discuss]

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自动机

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define N 1000000
using namespace std;
int m,n,sz;
char s[N];
int ch[N][30],fail[N],cnt[N],isend[N],pos[N],ans[N];
vector<int> pd;
void insert(int k)
{
  int len=strlen(s);
  int now=0;
  for (int i=0;i<len;i++)
   {
    int x=s[i]-'a';
    if (!ch[now][x]) ch[now][x]=++sz;
    cnt[ch[now][x]]++;
    now=ch[now][x];
   }
  isend[now]=1; pos[k]=now;
}
void makefail()
{
  queue<int> p;
  for (int i=0;i<26;i++)  if (ch[0][i])  p.push(ch[0][i]);
  pd.clear();
  while(!p.empty())
  {
   int now=p.front(); p.pop();
   pd.push_back(now); 
   for (int i=0;i<26;i++)
   {
    if (!ch[now][i])
     {
       ch[now][i]=ch[fail[now]][i];
       continue;
     }
    int x=ch[now][i];
    fail[x]=ch[fail[now]][i];
    p.push(x); 
   }
  }
}
void solve()
{
  for (int i=pd.size()-1;i>=0;i--)
   cnt[fail[pd[i]]]+=cnt[pd[i]];
}
int main()
{
 scanf("%d",&n);
 for (int i=1;i<=n;i++)
 {
  scanf("%s",s);
  insert(i);
 }
 makefail();
 solve();
 for (int i=1;i<=n;i++)
  printf("%d\n",cnt[pos[i]]);
 return 0;
}




你可能感兴趣的:(bzoj 3172: [Tjoi2013]单词)