码迷,mamicode.com
首页 > 其他好文 > 详细

【模板】AC自动机(加强版)

时间:2017-07-26 22:00:57      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:表示   ring   blog   pop   排列   make   com   i++   empty   

题目描述

技术分享个由小写字母组成的模式串以及一个文本串技术分享。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串技术分享中出现的次数最多。

输入输出格式

输入格式:

 

输入含多组数据。

每组数据的第一行为一个正整数技术分享,表示共有技术分享个模式串,技术分享

接下去技术分享行,每行一个长度小于等于技术分享的模式串。下一行是一个长度小于等于技术分享的文本串技术分享

输入结束标志为技术分享

 

输出格式:

 

对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。

 

输入输出样例

输入样例#1:
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
输出样例#1:
4
aba
2
alpha
haha

个人认为没有什么特别大的变化,记录一下,然后简单运用一下,就ok了,纯裸题,不过用c++自带的queue貌似有些慢,
应该可以优化一下。
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<cstring>
 6 #include<queue>
 7 using namespace std;
 8 
 9 int n,cnt=1,fzy[157];
10 char s[157][77];
11 struct Node
12 {
13     int c[26],suf,flag,mark;
14     void init()
15     {
16         suf=flag=mark=0;
17         memset(c,0,sizeof(c));    
18     }    
19 }tree[1000007];
20 
21 void init()
22 {
23     memset(fzy,0,sizeof(fzy));
24     for (int i=0;i<=cnt;i++)
25         tree[i].init();
26     cnt=1;    
27 }
28 void Ins(int num)
29 {
30     int head=1,l=strlen(s[num]);
31     for (int i=0;i<l;i++)
32     {
33         int now=s[num][i]-a;
34         if (!tree[head].c[now]) tree[head].c[now]=++cnt;
35         head=tree[head].c[now];
36     }
37     tree[head].flag++,tree[head].mark=num;
38 }
39 void Make_AC()
40 {
41     for (int i=0;i<26;i++) tree[0].c[i]=1;
42     int head=0,tail=1;
43     queue<int>q;
44     while (!q.empty()) q.pop();
45     tree[1].suf=0;
46     q.push(1);
47     while (!q.empty())
48     {
49         int u=q.front();
50         q.pop();
51         for (int i=0;i<26;i++)
52             if (tree[u].c[i])
53             {
54                 tree[tree[u].c[i]].suf=tree[tree[u].suf].c[i];
55                 q.push(tree[u].c[i]);
56             }
57             else tree[u].c[i]=tree[tree[u].suf].c[i];
58     }
59 }
60 void Solve()
61 {
62     char s1[1000007];
63     scanf("%s",s1);
64     int head=1,len=strlen(s1);
65     for (int i=0;i<len;i++)
66     {
67         int now=s1[i]-a;
68         head=tree[head].c[now];
69         for (int j=head;j&&tree[j].flag!=-1;j=tree[j].suf)
70             fzy[tree[j].mark]+=tree[j].flag;
71     }
72     int x=fzy[1];
73     for (int i=2;i<=n;i++)
74         if (x<fzy[i]) x=fzy[i];
75     printf("%d\n",x);    
76     for (int i=1;i<=n;i++) 
77         if (x==fzy[i]) printf("%s\n",s[i]);
78 }
79 int main()
80 {    
81     while (scanf("%d",&n)&&n)
82     {
83         init();
84         for (int i=1;i<=n;i++)
85             {scanf("%s",s[i]);Ins(i);}
86         Make_AC();
87         Solve();
88     }
89 }

 

 

【模板】AC自动机(加强版)

标签:表示   ring   blog   pop   排列   make   com   i++   empty   

原文地址:http://www.cnblogs.com/fengzhiyuan/p/7241810.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!