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\n",acmatch(s));
77     }
78     return 0;
79 }
View Code

 

 

 

 

 

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

 

 
posted on 2018-09-13 20:11  Frank-King  阅读(101)  评论(0编辑  收藏  举报