链接
https://www.luogu.org/problemnew/show/P3796
大意
给定 n n 个串和一个文本串,找出所有在文本串中出现次数最多的串(可能有多个),并输出出现的次数
思路
自动机,更改一下查找的部分即可
代码
#include<cstring>
#include<cstdio>
#include<queue>
#define zero(x) memset(x,0,sizeof(x))
using namespace std;char s[151][71],T[1000010];
queue<int>q;
int nxt[1000010],trie[1000010][26],num[1000010],tot,n,ans[1000010];
inline void build()//构造失配指针
{
for(register int i=0;i<26;i++) if(trie[0][i]) nxt[trie[0][i]]=0,q.push(trie[0][i]);
while(q.size())
{
int x=q.front();q.pop();
for(register int i=0;i<26;i++)
if(trie[x][i]) nxt[trie[x][i]]=trie[nxt[x]][i],q.push(trie[x][i]);
else trie[x][i]=trie[nxt[x]][i];
}
}
inline void insert(char* s,register int id)//插入s
{
int len=strlen(s),p=0;
for(register int i=0;i<len;i++)
{
int ch=s[i]-'a';
if(!trie[p][ch]) trie[p][ch]=++tot;
p=trie[p][ch];
}
num[p]=id;
}
inline void query(char *b)//查询
{
int len=strlen(b),p=0,maxn=0;
for(register int i=0;i<len;i++)
{
p=trie[p][b[i]-'a'];
if(num[p]) ans[num[p]]++;
for(register int t=nxt[p];t;t=nxt[t]) if(num[t]) ans[num[t]]++;//统计答案
}
for(register int i=1;i<=n;i++) maxn=max(ans[i],maxn);//找出最多出现次数
printf("%d\n",maxn);//输出
for(register int i=1;i<=n;i++) if(ans[i]==maxn) puts(s[i]);//输出
return;
}
signed main()
{
while(scanf("%d",&n),n)
{
zero(nxt);zero(trie);zero(num);zero(ans);tot=0;
for(register int i=1;i<=n;i++) scanf("%s",s[i]),insert(s[i],i);
build();
scanf("%s",T);
query(T);
}
}