题目描述
有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
模板题一道,就是输出很蛋疼。另外trie树写指针版真的快得多(1~2s),但是还是用数组比较好写。
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 5;
int mx = 0;
namespace Aho_Corasick {
int trie[maxn][26], fail[maxn], cnt, sum[maxn], fixed[maxn];
int init() {
cnt = 0, mx = 0;
memset(trie, 0, sizeof(trie));
memset(fail, 0, sizeof(fail));
memset(sum, 0, sizeof(sum));
memset(fixed, 0, sizeof(fixed));
fail[0] = -1;
}
int insert(char * s) {
int len = strlen(s);
int now = 0, id;
for(register int i = 0; i < len; ++i) {
id = s[i] - 'a';
if(trie[now][id]) now = trie[now][id];
else now = trie[now][id] = ++cnt;
}
++sum[now];
}
void create() {
queue<int > q;
q.push(0);
while(!q.empty()) {
int u = q.front();
q.pop();
for(register int i = 0; i < 26; ++i) {
if(!trie[u][i]) continue;
int p = fail[u];
while(~p && !trie[p][i])
p = fail[p];
if(p != -1) fail[trie[u][i]] = trie[p][i];
q.push(trie[u][i]);
}
}
}
void work(char * s) {
int len = strlen(s), now = 0;
for(register int i = 0; i < len; ++i) {
int id = s[i] - 'a';
while(now && !trie[now][id])
now = fail[now];
if(now != -1) now = trie[now][id];
int p = now;
while(p) {
++fixed[p];
if(sum[p]) mx = max(mx, fixed[p]);
p = fail[p];
}
}
}
void judge(char * s) {
int len = strlen(s), now = 0;
for(register int i = 0; i < len; ++i) {
if(!trie[now][s[i] - 'a']) return;
now = trie[now][s[i] - 'a'];
}
if(fixed[now] != mx) return ;
for(register int i = 1; i <= sum[now]; ++i)
printf("%s\n", s);
}
}
#define AC Aho_Corasick
int n, m;
char s[205][205], art[maxn];
char res[205];
int main() {
while(1) {
scanf("%d", &n);
if(n == 0) break;
AC::init();
for(register int i = 1; i <= n; ++i) {
scanf("%s", s[i]);
AC::insert(s[i]);
}
AC::create();
scanf("%s", art);
AC::work(art);
printf("%d\n", mx);
for(register int i = 1; i <= n; ++i)
AC::judge(s[i]);
}
return 0;
}
rockdu
没有帐号? 立即注册