题目描述
有NN个由小写字母组成的模式串以及一个文本串TT。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串TT中出现的次数最多。
输入格式
输入含多组数据。
每组数据的第一行为一个正整数NN,表示共有NN个模式串,1 \leq N \leq 1501≤N≤150。
接下去NN行,每行一个长度小于等于7070的模式串。下一行是一个长度小于等于10^6106的文本串TT。
输入结束标志为N=0N=0。
输出格式
对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。
输入输出样例
输入
2 aba bab ababababac 6 beta alpha haha delta dede tata dedeltalphahahahototatalpha 0输出
4 aba 2 alpha haha找到在母串中出现次数最多的那个子串,有多个就按照输入顺序输出,AC自动机模板的加强版
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<iomanip>
#include<math.h>
#include<sstream>
using namespace std;
typedef long long ll;
typedef double ld;
string mob[300010];
int num[300010];
int trip[300010][26];
int fail[300010];
int ans[300010];
int temp;
int n,siz;
void add(string s,int v)
{
int now=0;
for(int i=0; i<s.size(); i++)
{
int o=s[i]-'a';
if(!trip[now][o])
trip[now][o]=++siz;
now=trip[now][o];
}
num[now]=v;
}
void getfail()
{
int now=0;
queue<int>que;
for(int i=0; i<26; i++)
if(trip[0][i])
que.push(trip[0][i]),fail[trip[0][i]]=0;
while(!que.empty())
{
int u=que.front();
que.pop();
for(int i=0; i<26; i++)
{
int v=trip[u][i];
if(v)
{
fail[v]=trip[fail[u]][i];
que.push(v);
}
else
trip[u][i]=trip[fail[u]][i];
}
}
}
void query(string s)
{
int now=0;
for(int i=0; i<s.size(); i++)
{
now=trip[now][s[i]-'a'];
for(int j=now; j; j=fail[j])
ans[num[j]]++;
}
}
int main()
{
while(cin>>n&&n)
{
memset(num,0,sizeof(num));
memset(ans,0,sizeof(ans));
memset(trip,0,sizeof(trip));
memset(fail,0,sizeof(fail));
siz=0;
for(int i=1; i<=n; i++)
{
cin>>mob[i];
add(mob[i],i);
}
getfail();
string k;
cin>>k;
query(k);
temp=0;
for(int i=1; i<=n; i++)
if(ans[i]>temp)
temp=ans[i];
cout<<temp<<endl;
for(int i=1; i<=n; i++)
if(ans[i]==temp)
cout<<mob[i]<<endl;
}
return 0;
}