LA_4670_Dominating_Patterns_(AC自动机+map)

描述



https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2671

给出一个字符串和一些子串,求其中出现次数最多的子串.

分析



在AC自动机上面跑就行了.但是有一个要注意的地方,就是在输入文件里同一个子串重复出现.如果不特殊处理的话,后一个子串就会把Trie里的前一个子串覆盖掉.,所以我们可以用个map...

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const int maxn=150+5,maxl=1e6+5,maxnode=150*70+5;
 5 int n;
 6 char text[maxl],p[maxn][70+5];
 7 map <string,int> ms;
 8 struct Aho_Corasick{
 9     int ch[maxnode][26];
10     int f[maxnode],val[maxnode],last[maxnode],cnt[maxn];
11     int sz;
12     inline int idx(char c){ return c-‘a‘; }
13     void init(){
14         sz=1;
15         memset(ch[0],0,sizeof ch[0]);
16         memset(cnt,0,sizeof cnt);
17         ms.clear();
18     }
19     void insert(char *s,int v){
20         ms[string(s)]=v;
21         int u=0;
22         for(;*s;s++){
23             int c=idx(*s);
24             if(!ch[u][c]){
25                 memset(ch[++sz],0,sizeof ch[0]);
26                 val[sz]=0;
27                 ch[u][c]=sz;
28             }
29             u=ch[u][c];
30         }
31         val[u]=v;
32     }
33     void get_fail(){
34         queue <int> q;
35         f[0]=0;
36         for(int c=0;c<26;c++){
37             int u=ch[0][c];
38             if(u){ f[u]=0; q.push(u); }
39         }
40         while(!q.empty()){
41             int r=q.front(); q.pop();
42             for(int c=0;c<26;c++){
43                 int u=ch[r][c];
44                 if(!u){ ch[r][c]=ch[f[r]][c]; continue; }
45                 q.push(u);
46                 int v=f[r];
47                 f[u]=ch[v][c];
48                 last[u]=val[f[u]]?f[u]:last[f[u]];
49             }
50         }
51     }
52     void work(int j){
53         if(j){
54             cnt[val[j]]++;
55             work(last[j]);
56         }
57     }
58     void find(char *T){
59         int j=0;
60         for(;*T;T++){
61             int c=idx(*T);
62             while(j&&!ch[j][c]) j=f[j];
63             j=ch[j][c];
64             if(val[j]) work(j);
65             else work(last[j]);
66         }
67     }
68 }ac;
69 int main(){
70     while(scanf("%d",&n)&&n){
71         ac.init();
72         for(int i=1;i<=n;i++){
73             scanf("%s",p[i]);
74             ac.insert(p[i],i);
75         }
76         ac.get_fail();
77         scanf("%s",text);
78         ac.find(text);
79         int best=-1;
80         for(int i=1;i<=n;i++) best=max(best,ac.cnt[i]);
81         printf("%d\n",best);
82         for(int i=1;i<=n;i++) if(ac.cnt[ms[string(p[i])]]==best) printf("%s\n",p[i]);
83     }
84     return 0;
85 }

4670
Dominating Patterns
The archaeologists are going to decipher a very mysterious “language”. Now, they know many language
patterns; each pattern can be treated as a string on English letters (only lower case). As a sub string,
these patterns may appear more than one times in a large text string (also only lower case English
letters).
What matters most is that which patterns are the dominating patterns. Dominating pattern is the
pattern whose appearing times is not less than other patterns.
It is your job to find the dominating pattern(s) and their appearing times.
Input
The entire input contains multi cases. The first line of each case is an integer, which is the number of
patterns N , 1 ≤ N ≤ 150. Each of the following N lines contains one pattern, whose length is in range
[1, 70]. The rest of the case is one line contains a large string as the text to lookup, whose length is up
to 10 6 .
At the end of the input file, number ‘0’ indicates the end of input file.
Output
For each of the input cases, output the appearing times of the dominating pattern(s). If there are more
than one dominating pattern, output them in separate lines; and keep their input order to the output.
Sample Input
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
Sample Output
4
aba
2
alpha
haha

时间: 2024-12-14 02:53:41

LA_4670_Dominating_Patterns_(AC自动机+map)的相关文章

bzoj 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)

题目大意:略 由于字符集大,要用map维护Trie树 并不能用AC自动机的Trie图优化,不然内存会炸 所以我用AC自动机暴跳fail水过的 显然根据喵星人建AC自动机是不行的,所以要根据问题建 然而这题有一些很艮的地方: 1.如果一个喵的名和姓都被点到,那他只被点到了一次 2.询问的串可能相同 3.如果map中并不包含某个元素,但你强行用数组表示它,那么它会返回0,然后这个元素会被强行插入map并赋值成0 1 #include <map> 2 #include <queue> 3

【HDU】病毒侵袭持续中(AC自动机+map)

一开始一直WA,之后发现这道题不止一组输入,改成多组输入之后就过了. 利用map把每个字符串映射到它对应的结点上就行了. 11909467 2014-10-19 11:54:00 Accepted 3065 234MS 16912K 2754 B G++ KinderRiven #include<queue> #include<map> #include<cstdio> #include<string> #include<vector> #inc

hdu 5164 Matching on Array (用map实现的ac自动机)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5164 题意: 给出长度为n一个母串,给出m个长度为ki子串,匹配的条件是比率相同,如子串4 8 能和 1 2 4匹配.问所有子串在母串中出现多少次. 限制: 1 <= n,m <= 1e5 1 <= ki <= 300000 思路: 赤裸裸的ac自动机啊,不过next数组用map来实现,出题人脑洞真大. 这里有一点还要注意,hdu的g++,结构体里面不能开太大的东西,要不然他ce了还

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

HDU 2222 Keywords Search AC自动机

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67122    Accepted Submission(s): 22584 Problem Description In the modern time, Search engine came into the life of everybody lik

LA_3942 LA_4670 从字典树到AC自动机

首先看第一题,一道DP+字典树的题目,具体中文题意和题解见训练指南209页. 初看这题模型还很难想,看过蓝书提示之后发现,这实际上是一个标准DP题目:通过数组来储存后缀节点的出现次数.也就是用一颗字典树从后往前搜一发.最开始觉得这种搞法怕不是要炸时间,当时算成了O(N*N)毕竟1e5的数据不搞直接上N*N的大暴力...后来发现,字典树根本跑不完N因为题目限制字典树最多右100层左右. 实际上这道题旧思想和模型来说很好(因为直观地想半天还真想不出来..)但是实际实现起来很简单--撸一发字典树就好了

LightOJ 1427 Substring Frequency (II) (AC自动机)

题意:给定一个文本串和 n 个子串,问你子串在文本串出现的次数. 析:很明显的AC自动机,只要把先把子串进行失配处理,然后再去用文本串去匹配,在插入子串时就要标记每个串,注意串可能是相同的,这个我错了两次,最后匹配一次就OK了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib

hdu 4787 GRE Words Revenge 在线AC自动机

hdu 4787 GRE Words Revenge Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)Total Submission(s): 2505    Accepted Submission(s): 614 Problem Description Now Coach Pang is preparing for the Graduate Record Examina

[coci2012]覆盖字符串 AC自动机

给出一个长度为N的小写字母串,现在Mirko有M个若干长度为Li字符串.现在Mirko要用这M个字符串去覆盖给出的那个字符串的.覆盖时,必须保证:1.Mirko的字符串不能拆开,旋转:2.Mirko的字符串必须和给出的字符串的某一连续段完全一致才能覆盖,3.若干次覆盖可以部分重叠4.Mirko的字符串可以无限使用.求给出的字符串当中,有多少个字母是无法覆盖的. 小朋友们,作为一名长者,我认为我有必要向你们传授一些人生的经验~: 字符串的一堆函数,慎用慎用: 本人只因没有仔细认真,把strlen(