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

题目描述

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

输入输出格式

输入格式:

输入含多组数据。

每组数据的第一行为一个正整数N,表示共有N个模式串,1N150。

接下去N行,每行一个长度小于等于70的模式串。下一行是一个长度小于等于10^6的文本串TT。

输入结束标志为N=0

输出格式:

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

输入输出样例

输入样例#1: 
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
输出样例#1: 
4
aba
2
alpha
haha
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 long long read()
 7 {
 8     long long x=0,f=1;
 9     char ch=getchar();
10     while(ch>'9'||ch<'0')
11     {
12         if(ch=='-')
13             f=-1;
14         ch=getchar();
15     }
16     while(ch>='0'&&ch<='9')
17     {
18         x=x*10+ch-'0';
19         ch=getchar();
20     }
21     return x*f;
22 }
23 const int maxn=3e5+10;
24 string mob[maxn];
25 int num[maxn],ch[maxn][26],fail[maxn],ans[maxn];
26 int temp,n,siz;
27 void insert(string s,int v)
28 {
29     int now=0;
30     for(int i=0; i<s.size(); i++)
31     {
32         int o=s[i]-'a';
33         if(!ch[now][o])
34             ch[now][o]=++siz;
35         now=ch[now][o];
36     }
37     num[now]=v;
38 }
39 void getfail()
40 {
41     int now=0;
42     queue<int>q;
43     for(int i=0; i<26; i++)
44         if(ch[0][i])
45             q.push(ch[0][i]),fail[ch[0][i]]=0;
46     while(!q.empty())
47     {
48         int u=q.front();
49         q.pop();
50         for(int i=0; i<26; i++)
51         {
52             int v=ch[u][i];
53             if(v)
54                 fail[v]=ch[fail[u]][i],q.push(v);
55             else
56                 ch[u][i]=ch[fail[u]][i];
57         }
58     }
59 }
60 void query(string s)
61 {
62     int now=0;
63     for(int i=0; i<s.size(); i++)
64     {
65         now=ch[now][s[i]-'a'];
66         for(int j=now; j; j=fail[j])
67             ans[num[j]]++;
68     }
69 }
70 int main()
71 {
72     while(scanf("%d",&n)&&n)
73     {
74         memset(num,0,sizeof(num));
75         memset(ans,0,sizeof(ans));
76         memset(ch,0,sizeof(ch));
77         memset(fail,0,sizeof(fail));
78         siz=0;
79         for(int i=1; i<=n; i++)
80         {
81             cin>>mob[i];
82             insert(mob[i],i);
83         }
84         getfail();
85         string k;
86         cin>>k;
87         query(k);
88         temp=0;
89         for(int i=1; i<=n; i++)
90             if(ans[i]>temp)
91                 temp=ans[i];
92         printf("%d\n",temp);
93         for(int i=1; i<=n; i++)
94             if(ans[i]==temp)
95                 cout<<mob[i]<<"\n";
96     }
97     return 0;
98 }
View Code

 

转载于:https://www.cnblogs.com/liweilin/p/10190453.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值