hdu2222 Keywords Search

题目连接 

题意:每组数据中有n个子串,给出目标串,求出共有多少个子串在目标串中出现过,输出数量。

题解:妥妥的ac自动机(多模匹配算法),是个模板题。

 

ac自动机学习参考链接(大佬的图画的太棒了):

https://blog.csdn.net/weixin_40317006/article/details/81327188

https://blog.csdn.net/creatorx/article/details/7110084

 

链表版

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<string.h>
  4 #include<malloc.h>
  5 using namespace std;
  6 
  7 const int maxn=1e7+10;
  8 
  9 struct node
 10 {
 11     node *next[26];     //下一个字母
 12     node *fail;        //失败指针
 13     int sum;        //几个单词结点
 14 };
 15 
 16 node *root;
 17 node *newnode;
 18 int head,tail;
 19 node *q[maxn];
 20 char pattern[maxn];
 21 char key[100];
 22 int cnt;
 23 
 24 void insert(char *s)
 25 {
 26     node *p=root;
 27     for(int i=0;s[i];i++){
 28         int x=s[i]-'a';
 29         if(p->next[x]==NULL){
 30             newnode=(struct node*)malloc(sizeof(struct node));
 31             for(int j=0;j<26;j++) newnode->next[j]=0;
 32             newnode->sum=0;
 33             newnode->fail=0;
 34             p->next[x]=newnode;
 35         }
 36         p=p->next[x];
 37     }
 38     p->sum++;
 39 }
 40 
 41 void build_fail()
 42 {
 43     head=0;
 44     tail=1;
 45     q[head]=root;
 46     node *p;node *temp;
 47     while(head<tail){
 48         temp=q[head++];
 49         for(int i=0;i<26;i++){
 50             if(temp->next[i]){
 51                 if(temp==root){
 52                     temp->next[i]->fail=root;
 53                 }
 54                 else{
 55                     p=temp->fail;
 56                     while(p){
 57                         if(p->next[i]){
 58                             temp->next[i]->fail=p->next[i];
 59                             break;
 60                         }
 61                         p=p->fail;
 62                     }
 63                     if(!p) temp->next[i]->fail=root;
 64                 }
 65                 q[tail++]=temp->next[i];
 66             }
 67         }
 68     }
 69 }
 70 
 71 void ac_chicken(char *ch)
 72 {
 73     node *p=root;
 74     int len=strlen(ch);
 75     for(int i=0;i<len;i++){
 76         int x=ch[i]-'a';
 77         while(!p->next[x]&&p!=root) p=p->fail;  //找到这个字母
 78         p=p->next[x];   //p到这个节点
 79         if(!p) p=root;  //没有的话就是根节点
 80         node *temp=p;
 81         while(temp!=root){
 82             if(temp->sum){
 83                cnt+=temp->sum;
 84                temp->sum=0;
 85             }
 86             else break;
 87             temp=temp->fail;
 88         }
 89     }
 90 }
 91 
 92 int main()
 93 {
 94     int t,n;
 95     scanf("%d",&t);
 96     while(t--){
 97         root=(struct node*)malloc(sizeof(struct node));
 98         for(int i=0;i<26;i++) root->next[i]=0;
 99         root->fail=0;
100         root->sum=0;
101         cnt=0;
102         scanf("%d",&n);
103         for(int i=0;i<n;i++){
104             scanf("%s",key);
105             insert(key);
106         }
107         build_fail();
108         scanf("%s",pattern);
109 ac_chicken(pattern);
110 printf("%d\n",cnt); 111 } 112 return 0; 113 }

 

数组版(一定记得初始化!!不初始化会mle 鬼知道为什么-_-!!

 

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<string.h>
 4 #include<queue>
 5 using namespace std;
 6 
 7 const int maxn=1e6+10;
 8 int n,cnt=1;
 9 int tree[maxn][26],color[maxn],fail[maxn];
10 char pattern[2*maxn];
11 char key[100];
12 queue<int> q;
13 
14 void init()
15 {
16     memset(tree,0,sizeof(tree));
17     memset(color,0,sizeof(color));
18     memset(fail,0,sizeof(fail));
19     memset(key,0,sizeof(key));
20     memset(pattern,0,sizeof(pattern));
21     cnt=1;
22     while(!q.empty()) q.pop();
23 }
24 
25 void insert(char *s)
26 {
27     int u=1,len=strlen(s);
28     for(int i=0;i<len;i++){
29         int v=s[i]-'a';
30         if(!tree[u][v]) tree[u][v]=++cnt;
31         u=tree[u][v];
32     }
33     color[u]++;
34 }
35 
36 void build_fail()
37 {
38     for(int i=0;i<26;i++) tree[0][i]=1;  //一个非常重要的细节处理,我们加一个虚拟节点0,并将它的所有边都连到1,方便以后的运算
39     q.push(1);      //将根压入队列
40     fail[1]=0;
41     while(!q.empty()){
42         int u=q.front();
43         q.pop();
44         for(int i=0;i<26;i++){   //遍历所有儿子
45             if(!tree[u][i]){               //不存在该节点
46                 tree[u][i]=tree[fail[u]][i];
47                 continue;
48             }
49             fail[tree[u][i]]=tree[fail[u]][i];
50             q.push(tree[u][i]);   //存在实节点才压入队列
51         }
52     }
53 }
54 
55 int ac_chicken(char *ch)
56 {
57     int u=1,ans=0,len=strlen(ch);
58     for(int i=0;i<len;i++){
59         int v=ch[i]-'a';
60         int k=tree[u][v];
61         while(k>1&&color[k]){
62             ans+=color[k];
63             color[k]=0;
64             k=fail[k];
65         }
66         u=tree[u][v];
67     }
68     return ans;
69 }
70 
71 int main()
72 {
73     int t;
74     scanf("%d",&t);
75     while(t--){
76         init();
77         scanf("%d",&n);
78         for(int i=0;i<n;i++){
79             scanf("%s",pattern);
80             insert(pattern);
81         }
82         build_fail();
83         scanf("%s",key);
84         printf("%d\n",ac_chicken(key));
85     }
86     return 0;
87 }

 

全部评论

相关推荐

2025-12-14 11:43
黑龙江大学 Java
用微笑面对困难:确实比较烂,可以这么修改:加上大学的qs排名,然后大学简介要写一些,然后硕士大学加大加粗,科研经历第一句话都写上在复旦大学时,主要负责xxxx,简历左上角把学校logo写上,建议用复旦大学的简历模板
点赞 评论 收藏
分享
2025-12-12 19:01
南京航空航天大学 C++
秋招没咋投,准备&nbsp;wxg&nbsp;转正之后摆烂了。结果不堪字节&nbsp;HR&nbsp;的骚扰还是面了一下字节。之前想去字节的时候怎么面都挂。现在想着随便面一下结果三面技术面都意外顺利还有加面。十月中旬字节发了意向,wxg&nbsp;转正结果无响应。十月底字节拉了保温群,wxg&nbsp;口头通过,系统显示考核中。十一月初和字节&nbsp;ld&nbsp;交流之后得知&nbsp;base&nbsp;居然能选海外,甚至能小&nbsp;wlb&nbsp;一下,wxg&nbsp;无响应无人联系。十一月中旬把字节&nbsp;base&nbsp;转到了海外,wxg&nbsp;流程灰了,一问超时忘处理了,过两天又变考核中了。十一月下旬字节换了海外&nbsp;HR&nbsp;对接,问了期望薪资,wxg&nbsp;考核终于显示通过,无&nbsp;HR&nbsp;保温,无其他保温。十一月底给字节报了个天价,想吓吓他们,同时告诉微信字节要开了,微信无响应。同样十一月底字节&nbsp;HR&nbsp;告诉我确实给不到那么高,但是能拿期权补上,问能不能接受。微信无响应。同样十一月底字节&nbsp;HR&nbsp;告知了具体方案,符合预期。&nbsp;微信无响应。十二月上旬催&nbsp;wxg&nbsp;不开我就盲拒了,wxg&nbsp;HR&nbsp;火急火燎的打电话问情况,问期望。我给了一个不算夸张的总包数字,因为今年市场在涨,过了三天还不联系我,我再催,约时间下午打电话,非得在我给出的数字上压下去几万,微信又不差这点,为什么不能满足我,让我没有拒绝的理由呢?一番纠结抗争,求稳还是追求挑战,最终选择接受迎接新的挑战,因为堂吉诃德永远不会停下脚步!回想起来,在&nbsp;wxg&nbsp;谈薪的阶段,我认为并没有给予我一定的重视,即使&nbsp;HR&nbsp;表示我在实习期间的表现和之前的面评都很靠前。也没有感觉到想要争取我,虽然我表示拒了&nbsp;offer&nbsp;之后要给我加面委定&nbsp;t6&nbsp;再涨,但我三个月没面试让我面面委那就是白给,还是算了。有缘再见了我亲爱的&nbsp;wxg,再见了曾经的梦中情厂,再见亲爱的&nbsp;mt,再见亲爱的朋友们。也再见,北京的一切。我想润了。秋招结束,卸载牛客,下一个三年,下一个五年,下一个十年后再来看看。
面试中的大熊猫爱吃薯...:我嫉妒得狗眼通红
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务