zoukankan      html  css  js  c++  java
  • 【BZOJ】【3172】【TJOI2013】单词

    AC自动机


      Orz zyf

      玛雅一开始连题意都没看懂……意思就是给你一篇文章的N个单词,问每个单词在这篇文章中各出现了几次?(这篇文章=N个单词)

      那么我们建个AC自动机……对于每个单词来说,它出现的次数=以它为根的fail树的大小,即询问有多少点沿fail指针能走到这个单词的结束结点。

      但是我们有更简单的算法= =(orz zyf)

    AC自动机的话我们直接其实就是查询有多少个节点通过fail能到达该串的结束节点,既然这样符合条件的一定bfs的时候在该点之后
    那么我们按bfs逆序执行w[go[i]]+=w[i]即可。正确性显然。

      

     1 /**************************************************************
     2     Problem: 3172
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:4432 ms
     7     Memory:119436 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 3172
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 inline int getint(){
    23     int v=0,sign=1; char ch=getchar();
    24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    26     return v*sign;
    27 }
    28 const int N=1e6+10,INF=~0u>>2;
    29 typedef long long LL;
    30 /******************tamplate*********************/
    31 int n,cnt=1,pos[N];
    32 struct Trie{
    33     int ch[26],fail,w;
    34 }T[N];
    35 char s[N];
    36 void ins(char *s,int num){
    37     int x=1,y;
    38     rep(i,strlen(s)){
    39         y=s[i]-'a';
    40         if (!T[x].ch[y]) T[x].ch[y]=++cnt;
    41         x=T[x].ch[y];
    42         T[x].w++;
    43     }
    44     pos[num]=x;
    45 }
    46 int Q[N],l=0,r=-1;
    47 void make_fail(){
    48     Q[++r]=1;
    49     while(l<=r){
    50         int x=Q[l++],y,j;
    51         rep(i,26){
    52             j=T[x].fail;
    53             while(j && !T[j].ch[i]) j=T[j].fail;
    54             if (T[x].ch[i]){
    55                 y=T[x].ch[i];
    56                 T[y].fail=j ? T[j].ch[i] : 1;
    57                 Q[++r]=y;
    58             }else T[x].ch[i]=j ? T[j].ch[i] : 1;
    59         }
    60     }
    61 }
    62  
    63 int main(){
    64 #ifndef ONLINE_JUDGE
    65     freopen("3172.in","r",stdin);
    66     freopen("3172.out","w",stdout);
    67 #endif
    68     n=getint(); cnt=1;
    69     F(i,1,n){
    70         scanf("%s",s);
    71         ins(s,i);
    72     }
    73     make_fail();
    74     D(i,r,0) T[T[Q[i]].fail].w+=T[Q[i]].w;
    75     F(i,1,n) printf("%d
    ",T[pos[i]].w);
    76     return 0;
    77 }
    View Code

    3172: [Tjoi2013]单词

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

    [Submit][Status][Discuss]

      

  • 相关阅读:
    无声购票弹窗
    C#多线程与异步的区别
    关于adb驱动
    事务日志初探(二)---简单恢复模式
    预写式日志(Write-Ahead Logging (WAL))
    如果正确读取SQL Server中的扩展事件?
    索引初探(三)
    事务日志还原的次意外的操作失误
    索引初探(二)
    索引的初探(一)
  • 原文地址:https://www.cnblogs.com/Tunix/p/4396827.html
Copyright © 2011-2022 走看看