zoukankan      html  css  js  c++  java
  • [TJOI2013]单词(AC自动机+前缀和维护)

    链接:https://ac.nowcoder.com/acm/problem/20443
    来源:牛客网

    题目描述

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

    输入描述:

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

    输出描述:

    输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
    具体思路:首先在trie树上每次添加一个节点,这个节点的权值就+1,保存每个字符串最终节点在trie树上的编号。然后再去建立fail指针。当建立好fail指针的时候,跑一遍前缀和。
    具体跑前缀和的时候,每一个节点更新到这个节点的fail指针上就好了。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 const int mod = 1e9+7;
     5 const int maxn = 1e6+100;
     6 int ch[maxn][30],tot=0;
     7 char str[200+10][maxn];
     8 int val[maxn];
     9 int ans[maxn];
    10 int  add_trie(char st[])
    11 {
    12     int len=strlen(st);
    13     int p=0;
    14     for(int i=0; i<len; i++)
    15     {
    16         int to=st[i]-'a';
    17         if(!ch[p][to])
    18             ch[p][to]=++tot;
    19         p=ch[p][to];
    20         val[p]++;
    21     }
    22     return p;
    23 }
    24 int fail[maxn],last[maxn];
    25 int sto[maxn];
    26 int num=0;
    27 void get_fail()
    28 {
    29     queue<int>q;
    30     for(int i=0; i<=tot; i++)
    31         fail[i]=-1;
    32     q.push(0);
    33     while(!q.empty())
    34     {
    35         int top=q.front();
    36         q.pop();
    37         for(int i=0; i<26; i++)
    38         {
    39             int u=ch[top][i];
    40             if(u==0)
    41                 continue;
    42             sto[++num]=u;
    43             q.push(u);
    44             int v=fail[top];
    45             while(v!=-1&&!ch[v][i])
    46                 v=fail[v];
    47             fail[u]=(v==-1?0:ch[v][i]);
    48             last[u]=val[fail[u]]?fail[u]:last[fail[u]];
    49         }
    50     }
    51 }
    52 int n;
    53 void init()
    54 {
    55     for(int i=num; i>=1; i--)
    56     {
    57         val[fail[sto[i]]]+=val[sto[i]];
    58     }
    59 }
    60 void print()
    61 {
    62     for(int i=1; i<=n; i++)
    63     {
    64         printf("%d
    ",val[ans[i]]);
    65     }
    66 }
    67 int main()
    68 {
    69     scanf("%d",&n);
    70     for(int i=1; i<=n; i++)
    71     {
    72         scanf("%s",str[i]);
    73         ans[i] = add_trie(str[i]);
    74     }
    75     get_fail();
    76     init();
    77     print();
    78     return 0;
    79 }


  • 相关阅读:
    extend()和append()区别
    extend()和append()区别
    extend()和append()区别
    extend()和append()区别
    Ethtool工具源码剖析
    [数据库基础]——索引
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10877056.html
Copyright © 2011-2022 走看看