zoukankan      html  css  js  c++  java
  • BZOJ-3172: [Tjoi2013]单词 (AC自动姬 fail树)

    3172: [Tjoi2013]单词

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 4057  Solved: 1964
    [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

     

    Source

    这题把fail指针逆向形成了一个叫fail树的东西  fail树的父亲结点一定是儿子节点的子串!!!

     1 #include "bits/stdc++.h"
     2 using namespace std;
     3 typedef long long LL;
     4 const int MAX=1000006;
     5 int n;
     6 struct Aho{
     7     struct state{
     8         int next[26];
     9         int cnt,fail;
    10         state (){
    11             memset(next,0,sizeof(next));
    12             cnt=fail=0;
    13         }
    14     }sst[MAX];
    15     
    16     int q[MAX],low,high,tot,size,end[205],sum[MAX];
    17     
    18     void init(){
    19         int i,j;
    20         low=1,high=tot=size=0;
    21         memset(sum,0,sizeof(sum));
    22     }
    23     
    24     void insert(char *s){
    25         int i,j,ls=strlen(s);
    26         int now=0;
    27         for (i=0;i<ls;i++){
    28             char c=s[i];
    29             if (!sst[now].next[c-'a']) sst[now].next[c-'a']=++size;
    30             now=sst[now].next[c-'a'];
    31             sum[now]++;
    32         }
    33         sst[now].cnt++;
    34         end[++tot]=now;
    35     }
    36     
    37     void build(){
    38         int i,j;
    39         int now=0;
    40         sst[0].fail=-1;
    41         q[++high]=0;
    42         while (low<=high){
    43             int u=q[low];
    44             low++;
    45             for (i=0;i<26;i++){
    46                 if (sst[u].next[i]){
    47                     if (u==0) sst[sst[u].next[i]].fail=0;
    48                     else{
    49                         int v=sst[u].fail;
    50                         while (v!=-1){
    51                             if (sst[v].next[i]){//注意 
    52                                 sst[sst[u].next[i]].fail=sst[v].next[i];
    53                                 break;
    54                             }
    55                             v=sst[v].fail;
    56                         }
    57                         if (v==-1)
    58                             sst[sst[u].next[i]].fail=0;
    59                     }
    60                     q[++high]=sst[u].next[i];
    61                 }
    62             }
    63         }
    64         for (;high;high--) sum[sst[q[high]].fail]+=sum[q[high]];//注意 
    65     }
    66 }aho;
    67 int main(){
    68     freopen ("word.in","r",stdin);
    69     freopen ("word.out","w",stdout);
    70     int i,j;char s[MAX];
    71     aho.init();
    72     scanf("%d
    ",&n);
    73     for (i=1;i<=n;i++){
    74         gets(s);
    75         aho.insert(s);
    76     }
    77     aho.build();
    78     for (i=1;i<=n;i++){
    79         printf("%d
    ",aho.sum[aho.end[i]]);
    80     }
    81     return 0;
    82 }
    未来是什么样,未来会发生什么,谁也不知道。 但是我知道, 起码从今天开始努力, 肯定比从明天开始努力, 要快一天实现梦想。 千里之行,始于足下! ——《那年那兔那些事儿》
  • 相关阅读:
    linux_进程管理
    Linux-日志管理
    Httpd
    Linux-源码安装包管理
    Linux-计划任务管理
    Linux-LVM管理
    Linux-系统磁盘管理
    Linux-yum工具的使用
    Linux-rpm包管理
    Linux-网络进阶管理
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/7354152.html
Copyright © 2011-2022 走看看