zoukankan      html  css  js  c++  java
  • 模板 Fail树

    fail树就是将Trie图的Fail指针反指,从而生成一棵树,这个树的性质是:子节点对应字符串为以当前串为后缀,而子节点为原串的前缀,前缀的后缀就是嵌套在原串中的子串。

    模板:BZOJ3172

    Description

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

    Input

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

    Output

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

    Sample Input

    3
    a
    aa
    aaa

    Sample Output

    6
    3
    1
    建完fail树统计子节点个数即可。
    代码:
     1 #include<queue>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 struct trnt{
     6     int ch[26];
     7     int fl;
     8     int wgt;
     9     int hd;
    10 }tr[2000000];
    11 struct ent{
    12     int twd;
    13     int lst;
    14 }e[1000000];
    15 int fnd[1000];
    16 char tmp[2000000];
    17 int cnt;
    18 int siz;
    19 int n;
    20 std::queue<int>Q;
    21 void ade(int f,int t)
    22 {
    23     cnt++;
    24     e[cnt].twd=t;
    25     e[cnt].lst=tr[f].hd;
    26     tr[f].hd=cnt;
    27 }
    28 void add(char *a,int x)
    29 {
    30     int root=0;
    31     int len=strlen(a+1);
    32     for(int i=1;i<=len;i++)
    33     {
    34         int c=a[i]-'a';
    35         if(!tr[root].ch[c])
    36             tr[root].ch[c]=++siz;
    37         root=tr[root].ch[c];
    38         tr[root].wgt++;
    39     }
    40     fnd[x]=root;
    41     return ;
    42 }
    43 void Build()
    44 {
    45     int root=0;
    46     for(int i=0;i<26;i++)
    47         if(tr[root].ch[i])
    48             Q.push(tr[root].ch[i]);
    49     while(!Q.empty())
    50     {
    51         root=Q.front();
    52         Q.pop();
    53         for(int i=0;i<26;i++)
    54         {
    55             if(tr[root].ch[i])
    56             {
    57                 tr[tr[root].ch[i]].fl=tr[tr[root].fl].ch[i];
    58                 Q.push(tr[root].ch[i]);
    59             }else
    60                 tr[root].ch[i]=tr[tr[root].fl].ch[i];
    61         }
    62     }
    63     /*--------------------------以上是Trie图-------------------*/
    64     
    65     
    66     
    67     /*--------------------------以下为fail树-------------------*/ 
    68     for(int i=1;i<=siz;i++)
    69         ade(tr[i].fl,i); 
    70     return ;
    71 }
    72 void dfs(int x)
    73 {
    74     for(int i=tr[x].hd;i;i=e[i].lst)
    75     {
    76         int to=e[i].twd;
    77         dfs(to);
    78         tr[x].wgt+=tr[to].wgt;
    79     }
    80 }
    81 int main()
    82 {
    83     scanf("%d",&n);
    84     for(int i=1;i<=n;i++)
    85     {
    86         scanf("%s",tmp+1);
    87         add(tmp,i);
    88     }
    89     Build();
    90     dfs(0);
    91     for(int i=1;i<=n;i++)
    92         printf("%d
    ",tr[fnd[i]].wgt);
    93     return 0;
    94 }
  • 相关阅读:
    TDirectory.GetParent获取指定目录的父目录
    TDirectory.GetLogicalDrives获取本地逻辑驱动器
    获取设置目录创建、访问、修改时间
    TDirectory.GetLastAccessTime获取指定目录最后访问时间
    TDirectory.GetDirectoryRoot获取指定目录的根目录
    「洛谷P1262」间谍网络 解题报告
    「洛谷P1198」 [JSOI2008]最大数 解题报告
    「洛谷P3931」 SAC E#1
    「UVA1328」「POJ1961」 Period 解题报告
    「博客美化」I 页面的CSS
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9672678.html
Copyright © 2011-2022 走看看