题目描述
有NN个由小写字母组成的模式串以及一个文本串TT。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串TT中出现的次数最多。
输入输出格式
输入格式:
输入含多组数据。
每组数据的第一行为一个正整数NN,表示共有NN个模式串,1 \leq N \leq 1501≤N≤150。
接下去NN行,每行一个长度小于等于7070的模式串。下一行是一个长度小于等于10^6106的文本串TT。
输入结束标志为N=0N=0。
输出格式:
对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。
输入输出样例
输入样例#1: 复制
2 aba bab ababababac 6 beta alpha haha delta dede tata dedeltalphahahahototatalpha 0
输出样例#1: 复制
4 aba 2 alpha haha
解题思路
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
#include <cstring>
#define maxn 1000005
using namespace std;
struct trie{
int e; //是第几个模式串的尾字母
int fail;
int next[26];
}tree[maxn];
struct T{
string str;
int x, i; //str出现的次数,str是第几个输入的
bool operator<(const T& a)const{
if(x != a.x)
return x > a.x;
else
return i < a.i;
}
}ans[155];
const int root = 0;
int cnt;
void clean(int x) //清除节点信息
{
memset(tree[x].next, 0, sizeof(tree[x].next));
tree[x].e = 0;
tree[x].fail = 0;
}
void build(string str, int index) //建树
{
int now = root;
for(int i = 0; i < str.size(); i ++){
if(!tree[now].next[str[i]-'a']){
tree[now].next[str[i]-'a'] = ++cnt;
clean(cnt); //清除新增节点的旧信息
}
now = tree[now].next[str[i]-'a'];
}
tree[now].e = index;
}
void get_fail()
{
queue<int> que;
for(int i = 0; i < 26; i ++){
if(tree[0].next[i]){
tree[tree[0].next[i]].fail = 0;
que.push(tree[0].next[i]);
}
}
while(!que.empty()){
int now = que.front();
que.pop();
for(int i = 0; i < 26; i ++){
if(tree[now].next[i]){
tree[tree[now].next[i]].fail = tree[tree[now].fail].next[i];
que.push(tree[now].next[i]);
}
else
tree[now].next[i] = tree[tree[now].fail].next[i];
}
}
}
void ac_query(string str) //匹配
{
int now = root;
for(int i = 0; i < str.size(); i ++){
now = tree[now].next[str[i]-'a'];
int u = now;
while(u){
ans[tree[u].e].x ++;
u = tree[u].fail;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
int n;
while(cin >> n && n){
cnt = 0;
clean(cnt); //清除根节点旧信息
for(int i = 1; i <= n; i ++){
string str;
cin >> str;
ans[i].str = str;
ans[i].i = i;
ans[i].x = 0;
build(str, i);
}
get_fail();
string s;
cin >> s;
ac_query(s);
sort(ans + 1, ans + n + 1);
int maxx = ans[1].x;
cout << maxx << endl;
for(int i = 1; i <= n; i ++){
if(ans[i].x == maxx)
cout << ans[i].str << endl;
else
break;
}
}
return 0;
}