• HDU 2222 Keywords Search 【ac自动机】


    HDU  2222  Keywords  Search

     

    题面见链接。

    题解:

    第一次学 AC 自动机,感觉差不多掌握基础了吧。

    这是一道入门模板题。就是给定文本串,和一些模式串,求模式串在文本串出现的个数。

    AC自动机主要步骤:
    1、先建一棵 trie 树,然后记录该点是否为某模式串的最后一位节点,且以这一个节点结尾的模式串的个数。

    2、预处理  fail  指针。 x 的 fail 指针连的是  fa[x]  的  fail  的  nxt  。目的是为了保证  fail  指针连的节点的模式串是 以 x 结尾的模式串的后缀。这样才能统计答案。

    3、开始 AC 自动机主过程:从根节点开始按照文本串一位一位往下匹配。找到一个节点就检查他的  fail  节点是否能够加入答案,如果可以则加入答案,并标记为“已搜过”,下次就不用再搜一遍,提高时间效率。

    贴代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=500005;
     4 int t,n,rt,tot,q[N];
     5 struct node{
     6     int nxt[26];
     7     int sum,fail;
     8 }e[N];
     9 char s[N<<1];
    10 inline void insert(char *s)
    11 {
    12     rt=0;
    13     for (int i=0; s[i]; i++)
    14     {
    15         if (!e[rt].nxt[s[i]-'a'])
    16           e[rt].nxt[s[i]-'a']=++tot;
    17         rt=e[rt].nxt[s[i]-'a'];
    18     }
    19     e[rt].sum++;
    20 }
    21 inline void getfail()
    22 {
    23     int head=0,tail=1;
    24     q[1]=0;
    25     while (head<tail)
    26     {
    27         int x=q[++head];
    28         for (int i=0; i<26; i++)
    29         {
    30             if (int y=e[x].nxt[i])
    31             {
    32                 if (x==0) e[y].fail=0;
    33                 else {
    34                     int tmp=e[x].fail;
    35                     while (tmp && e[tmp].nxt[i]==0)
    36                       tmp=e[tmp].fail;
    37                     e[y].fail=e[tmp].nxt[i];
    38                 }
    39                 q[++tail]=y;
    40             }
    41         }
    42     }
    43 }
    44 inline int acmatch(char *s)
    45 {
    46     getfail();
    47     rt=0;
    48     int cnt=0;
    49     for (int i=0; s[i]; i++)
    50     {
    51         while (rt && e[rt].nxt[s[i]-'a']==0)
    52           rt=e[rt].fail;
    53         int y=rt=e[rt].nxt[s[i]-'a'];
    54         while (y && ~e[y].sum)
    55         {
    56             cnt+=e[y].sum;
    57             e[y].sum=-1;
    58             y=e[y].fail;
    59         }
    60     }
    61     return cnt;
    62 }
    63 int main()
    64 {
    65     scanf("%d",&t);
    66     while (t--)
    67     {
    68         memset(e,0,sizeof(e)); tot=0;
    69         scanf("%d",&n);
    70         for (int i=1; i<=n; i++)
    71         {
    72             scanf("%s",s);
    73             insert(s);
    74         }
    75         scanf("%s",s);
    76         printf("%d
    ",acmatch(s));
    77     }
    78     return 0;
    79 }
    View Code

    加油加油加油!!!fighting fighting fighting!!!

     

     
  • 相关阅读:
    Redis 集合(Set)
    北京Uber优步司机奖励政策(1月21日)
    成都Uber优步司机奖励政策(1月21日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月21日)
    全国各城市Uber客服联系方式(电话、邮箱、微博)
    成都Uber优步司机奖励政策(1月20日)
    北京Uber优步司机奖励政策(1月20日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月20日)
    Linq聚合函数使用
    Linq查询案例
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9642837.html
Copyright © 2020-2023  润新知