/*
AC自动机,对多个模式串匹配,查找给出的文本串有多少个出现在模式串中
最简单的模板,需要修改
*/
const int N = maxn*8; //N表示n*m,n为模式串的个数,m为模式串的长度
struct AC_automaton {
int tr[N][26], tot;
int e[N], fail[N];
void init(){
memset(tr, 0, sizeof(tr));
memset(e, 0, sizeof(e));
memset(fail, 0, sizeof(fail));
}
void insert(char *s) {
int u = 0;
for (int i = 1; s[i]; i++) {
if (!tr[u][s[i] - 'a']) tr[u][s[i] - 'a'] = ++tot;
u = tr[u][s[i] - 'a'];
}
e[u]++; //模式串有可能有一样的
}
queue<int> q;
void build() { //fail指针的构建
for (int i = 0; i < 26; i++)
if (tr[0][i]) q.push(tr[0][i]);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if (tr[u][i])
fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
else
tr[u][i] = tr[fail[u]][i];
}
}
}
int query(char *t) {
int u = 0, res = 0;
for (int i = 1; t[i]; i++) {
u = tr[u][t[i] - 'a']; // 转移
for (int j = u; j && e[j] != -1; j = fail[j]) { //如果存在以此为结尾的话就增加一个匹配串
res += e[j], e[j] = -1;
}
}
return res;
}
}ac;
洛谷模板一,简单版
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
/*
AC自动机,对多个模式串匹配,查找给出的文本串有多少个出现在模式串中
最简单的模板,
*/
const int N = maxn*8; //N表示n*m,n为模式串的个数,m为模式串的长度
struct AC_automaton {
int tr[N][26], tot;
int e[N], fail[N];
void init(){
memset(tr, 0, sizeof(tr));
memset(e, 0, sizeof(e));
memset(fail, 0, sizeof(fail));
}
void insert(char *s) {
int u = 0;
for (int i = 1; s[i]; i++) {
if (!tr[u][s[i] - 'a']) tr[u][s[i] - 'a'] = ++tot;
u = tr[u][s[i] - 'a'];
}
e[u]++; //模式串有可能有一样的
}
queue<int> q;
void build() { //fail指针的构建
for (int i = 0; i < 26; i++)
if (tr[0][i]) q.push(tr[0][i]);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if (tr[u][i])
fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
else
tr[u][i] = tr[fail[u]][i];
}
}
}
int query(char *t) {
int u = 0, res = 0;
for (int i = 1; t[i]; i++) {
u = tr[u][t[i] - 'a']; // 转移
for (int j = u; j && e[j] != -1; j = fail[j]) { //如果存在以此为结尾的话就增加一个匹配串
res += e[j], e[j] = -1;
}
}
return res;
}
}ac;
char str[maxn];
int main(){
int n;scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%s", str+1), ac.insert(str);
ac.build();
scanf("%s", str+1);
printf("%d\n", ac.query(str));
return 0;
}
洛谷模板二加强版
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
const int N = 156*80;
/*
AC自动机,对多个模式串匹配,查找给出的文本串有多少个出现在模式串中
*/
struct AC_automaton {
int tr[N][26], tot; //tr为字典树
int e[N], fail[N],val[N]; //e为模式串结尾异或,fail为失配指针,val记录出现次数
int cnt[N]; //cnt记录模式串在文本串中出现的次数
void init() {
memset(fail, 0, sizeof(fail));
memset(tr, 0, sizeof(tr));
memset(val, 0, sizeof(val));
memset(cnt, 0, sizeof(cnt));
memset(e, 0, sizeof(e));
tot = 0;
}
void insert(char *s, int id) {
int u = 0;
for (int i = 0; s[i]; i++) {
if (!tr[u][s[i]-'a']) tr[u][s[i]-'a'] = ++tot;
u = tr[u][s[i]-'a'];
}
e[u]=id;
}
queue<int> q;
void build() {
for (int i = 0; i < 26; i++)
if (tr[0][i]) q.push(tr[0][i]);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if (tr[u][i])
fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
else
tr[u][i] = tr[fail[u]][i];
}
}
}
int query(char *t) { //返回最大的出现次数
int u = 0, res = 0;
for (int i = 0; t[i]; i++) {
u = tr[u][t[i] - 'a']; // 转移
for (int j = u; j ; j = fail[j]) {
val[j]++;
}
}
for(int i = 0; i <= tot; i++){
if(e[i]){
res=max(res, val[i]);
cnt[e[i]]=val[i];
}
}
return res;
}
}ac;
char s[200][80];
char str[maxn];
int main() {
int n;
while(scanf("%d", &n), n){
ac.init();
for(int i = 1; i <= n; i++) scanf("%s", s[i]), ac.insert(s[i], i);
scanf("%s", str);
ac.build();
int x=ac.query(str);
printf("%d\n", x);
for(int i = 1; i <= n; i++){
if(ac.cnt[i]==x) printf("%s\n", s[i]);
}
}
return 0;
}