UVALive 4670 Dominating Patterns (AC自动机)

时间:2023-03-09 17:53:07
UVALive 4670 Dominating Patterns (AC自动机)

AC自动机的裸题。学了kmp和Trie以后不难看懂。

有一些变化,比如0的定义和f的指向,和建立失配边,以及多了后缀连接数组last。没有试过把失配边直接当成普通边(一开始还是先这样写吧)。

#include<bits/stdc++.h>
using namespace std; const int maxlen = 1e6+, maxnds = *+, sigma_size = , maxsubs = ;
char str[maxlen]; #define idx(x) x-'a';
int last[maxnds];//后缀连接 为0表示空
int ch[maxnds][sigma_size];
int val[maxnds];
int nds;
char subs[maxsubs][];
int cnt[maxsubs+];
int f[maxnds]; void init() {
memset(ch,,sizeof(ch)); last[] = ; val[] = ; nds = ;
memset(cnt,,sizeof(cnt));
} void cal(int j)
{
while(j){
cnt[val[j]]++;
j = last[j];
}
} void Find(char *t)
{
for(int i = , j = ; t[i] ; i++){
int c = idx(t[i]);
while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if(val[j]) cal(j);
else if(last[j]) cal(last[j]);
}
} int getF()
{
queue<int> q;
f[] = ;
for(int c = ; c < sigma_size; c++){
int u = ch[][c];
if(u) { f[u] = ; q.push(u); last[u] = ; }
} while(q.size()){
int r = q.front(); q.pop();
for(int c = ; c < sigma_size; c++){
int u = ch[r][c];
if(!u) continue;
q.push(u);
int v = f[r];
while(v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
} void add(char *s,int str_id)
{
int u = ;
for(int i = ; s[i]; i++){
int c = idx(s[i]);
if(!ch[u][c]){
memset(ch[nds],,sizeof(ch[nds]));
val[nds] = ;
ch[u][c] = nds++;
}
u = ch[u][c];
}
val[u] = str_id;
} int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d\n",&n),n){
init();
for(int i = ; i <= n; i++){
scanf("%s",subs[i]);
add(subs[i],i);
}
getF();
scanf("%s",str);
Find(str);
int best = *max_element(cnt+,cnt++n);
printf("%d\n",best);
for(int i = ; i <= n; i++){
if(cnt[i] == best) puts(subs[i]);
}
}
return ;
}