传送门

题意: 给你n个模式串, 再给你一个 文本串,问模式串在文本串中出现次数最多是多少。

   出现次数最多的模式串有哪些。

解: 模版题。

#include <bits/stdc++.h>
#define LL long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define mem(i, j) memset(i, j, sizeof(i))
using namespace std;
const int N = * + , M = ;
map<string, int> vis;
char s[], b[][];
struct Trie {
int a[N][M], tot, val[N], Fail[N], last[N];
///last[j]:节点j沿着失配指针往回走时,遇到的下一个单词节点的编号
void init() {
mem(a[], -); tot = ; val[] = -; last[] = ;
}
int get(char Q) {
return Q - 'a';
}
void join(char s[], int v) {
int len = strlen(s); int now = ;
rep(i, , len - ) {
int id = get(s[i]);
if(a[now][id] == -) {
mem(a[tot], -);
val[tot] = -;
a[now][id] = tot++;
}
now = a[now][id];
}
val[now] = v;
}
void getFail() {
queue<int>Q; while(!Q.empty()) Q.pop();
Fail[] = ;
rep(i, , M - ) {
if(a[][i] == -) a[][i] = ;
else {
Fail[a[][i]] = ;
Q.push(a[][i]);
last[a[][i]] = ;
}
}
while(!Q.empty()) {
int now = Q.front(); Q.pop();
rep(i, , M - ) {
int u = a[now][i];
if(a[now][i] == -) a[now][i] = a[Fail[now]][i];
else {
Fail[u] = a[Fail[now]][i];
Q.push(u);
last[u] = val[Fail[u]] == - ? last[Fail[u]] : Fail[u];
}
}
}
}
int num[];
void print(int x) {
if(x) {
num[val[x]]++;
print(last[x]);
}
}
void query(char s[], int n) {
mem(num, );
int len = strlen(s);
int now = ;
rep(i, , len - ) {
now = a[now][get(s[i])];
if(val[now] != -) print(now);
else if(last[now] != -) print(last[now]);
}
int ma = ;
rep(i, , n) {
ma = max(ma, num[i]);
}
printf("%d\n", ma);
rep(i, , n) {
if(num[vis[b[i]]] == ma) {
printf("%s\n", b[i]);
}
}
}
};
Trie AC;
int main() {
int n;
while(scanf("%d", &n) && n) {
AC.init(); vis.clear();
rep(i, , n) {
scanf("%s", b[i]);
AC.join(b[i], i);
vis[b[i]] = i;
}
AC.getFail();
scanf("%s", s);
AC.query(s, n);
}
return ;
}
05-11 14:48