题目描述
有个由小写字母组成的模式串以及一个文本串。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串中出现的次数最多。
输入输出格式
输入格式:
输入含多组数据。
每组数据的第一行为一个正整数,表示共有个模式串,。
接下去行,每行一个长度小于等于的模式串。下一行是一个长度小于等于的文本串。
输入结束标志为。
输出格式:
对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。
输入输出样例
输入样例#1:
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
输出样例#1:
4
aba
2
alpha
haha
题解
在简单版上稍加改动,记录每个单词结束的节点位置,记录出现次数即可
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
char s[151][71],m[1000001];
int tot,n,a[1000001][26],danger[1000001],point[1000001],Hash[1000001],ans[151];
int q[1000001];
inline void ins(int x)
{
int now=1,l=strlen(s[x]);
for (int i=0;i<l;i++)
{
int t=s[x][i]-'a';
if (!a[now][t]) a[now][t]=++tot;
now=a[now][t];
}
Hash[now]=x;
}
inline void acmach()
{
int Head=0,tail=1;
q[1]=1;point[1]=0;
while (Head!=tail)
{
int now=q[++Head];
for (int i=0;i<26;i++)
if (a[now][i])
{
point[a[now][i]]=a[point[now]][i];
q[++tail]=a[now][i];
}
else a[now][i]=a[point[now]][i];
}
}
inline void solve()
{
int now=1,l=strlen(m);
for (int i=0;i<l;i++)
{
int t=m[i]-'a';
now=a[now][t];
for (int j=now;j;j=point[j])
if (Hash[j]) ans[Hash[j]]++;
}
}
int main()
{
n=read();
for (int i=0;i<26;i++) a[0][i]=1;
while (n)
{
tot=1;
for (int i=1;i<=n;i++)
{
scanf("%s",s[i]);
ins(i);
}
acmach();
scanf("%s",m);
solve();
int mx=0;
for (int i=1;i<=n;i++)
mx=max(mx,ans[i]);
printf("%d\n",mx);
for (int i=1;i<=n;i++)
{
if (mx==ans[i]) puts(s[i]);
ans[i]=0;
}
for (int i=1;i<=tot;i++)
{
Hash[i]=point[i]=danger[i]=0;
for (int j=0;j<26;j++)
a[i][j]=0;
}
n=read();
}
return 0;
}