您的位置:首页 > 其它

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

2018-08-08 16:45 423 查看

题目描述

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

输入输出格式

输入格式:

输入含多组数据。

每组数据的第一行为一个正整数 NNN ,表示共有 NNN 个模式串, 1≤N≤1501 \leq N \leq 1501≤N≤150 。

接下去 NNN 行,每行一个长度小于等于 707070 的模式串。下一行是一个长度小于等于 10610^6106 的文本串 TTT 。

输入结束标志为 N=0N=0N=0 。

输出格式:

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

输入输出样例

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


输出样例#1:
4
aba
2
alpha
haha


Solution:

  额,还是比较板子的AC自动机。

  略过AC自动机的构建(本题最好搞个后缀链接的优化),我们只需要在匹配的时候,记录一下各字符串出现的次数,最后比较一下就好了,坑点是除了字符串其它所有数组都要清0(trie,end,fail,last,cnt,num)。

  其实本题原题蓝书上有,那里会有重复的模式串,而本题没有,重复的模式串会在trie树中覆盖掉前面出现的字符串的end,可以思考一下加加强版,实现方法很多。

代码:

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=10305,M=1000005;
int trie
[26],cnt,end
,n,num[155],last
,fail
;
char s[155][72],t[M];

il void cler(){
memset(trie,0,sizeof(trie));
memset(num,0,sizeof(num));
memset(end,0,sizeof(end));
memset(fail,0,sizeof(fail));
memset(last,0,sizeof(last));
cnt=0;
}

il void insert(char *s,int id){
int len=strlen(s)-1,p=0,x;
For(i,0,len){
x=s[i]-'a';
if(!trie[p][x])trie[p][x]=++cnt;
p=trie[p][x];
}
end[p]=id;
}

il void bfs(){
queue<int>q;
For(i,0,25) if(trie[0][i]) fail[trie[0][i]]=0,q.push(trie[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
For(i,0,25){
int v=trie[u][i];
if(v) fail[v]=trie[fail[u]][i],last[v]=end[fail[v]]?fail[v]:last[fail[v]],q.push(v);
else trie[u][i]=trie[fail[u]][i];
}
}
}

il void query(char *t){
int len=strlen(t)-1,p=0,ans=0;
For(i,0,len){
p=trie[p][t[i]-'a'];
for(int j=p;j;j=last[j]) if(end[j]) num[end[j]]++;
}
For(i,1,n) ans=max(num[i],ans);
printf("%d\n",ans);
For(i,1,n) if(num[i]==ans) puts(s[i]);
}

int main(){
while(scanf("%d",&n)==1){
if(!n) exit(0);
cler();
For(i,1,n) scanf("%s",s[i]),insert(s[i],i);
bfs();
scanf("%s",t);
query(t);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: