题解 P3796 【【模板】AC自动机(加强版)】
ac自动机裸题
虽说是加强版,不过其实就是稍微换了下求的东西,还是很裸的
具体改动的地方在代码里给出
上菜:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 300000+5;
const int SIGMA_SIZE = 26;
int maxx = 0;//得出的最大大数目答案
char p[200][105];//用来输出字符答案
int ans[200];//唯一加的地方,用来存答案
char T[1000000+5];
queue <int> qe;
//ac自动机 机体qvq ps:感觉这种自动机写起来最好看(雾
struct AC_automata
{
int ch[maxn][26], val[maxn], f[maxn], cnt = 0;
void clear()//给数组清零
{
cnt = maxx = 0;
for(int i = 0; i < maxn; ++i)
{
val[i] = f[i] = 0;
for(int j = 0; j < 26; ++j)ch[i][j] = 0;
}
memset(ans, 0, sizeof ans);
}
void insert(char *s, int num)
{
int now = 0;
for(int i = 0; i < strlen(s); i++)
{
if(!ch[now][s[i]-'a'])ch[now][s[i]-'a'] = ++cnt;
now = ch[now][s[i]-'a'];
}
val[now] = num;
}
void getFail()
{
for(int i = 0; i < SIGMA_SIZE; i++)if(ch[0][i])qe.push(ch[0][i]);
while(!qe.empty())
{
int u = qe.front();qe.pop();
for(int i = 0; i < SIGMA_SIZE; i++)
{
if(ch[u][i]){f[ch[u][i]] = ch[f[u]][i];qe.push(ch[u][i]);}
else ch[u][i] = ch[f[u]][i];
}
}
}
void find()
{
int len = strlen(T), now = 0;
for(int i = 0; i < len; i++)
{
now = ch[now][T[i]-'a'];
for(int t = now; t; t = f[t]){if(val[t]){ans[val[t]]++;if(t!=0)maxx = max(maxx,ans[val[t]]);}}
}
}
}AC;
int n;
int main()
{
while(scanf("%d", &n) == 1 && n)
{
AC.clear();
for(int i = 1; i <= n; ++i)
scanf(" %s", p[i]),AC.insert(p[i], i);
AC.getFail();
scanf("%s", T);
AC.find();
printf("%d\n", maxx);
for(int i = 1; i <= n; ++i)if(ans[i] == maxx)printf("%s\n", p[i]);
//如果找到和答案一样数目的单词就输出
}
return 0;
}