1036 : Trie图 (AC自动机)

时间:2022-04-01 04:54:22

题目大意: 输入 n 个目标单词和一个文本串,判断文本串中是否存在某些目标单词。

思路 赤裸裸的 AC自动机。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define INF 0x7fffffff int ch[1000010][26],f[1000010],last[1000010],val[1000010],nz,found;
char s[1000000],T[1000010]; void insert(){
int i,j,u = 0,len = strlen(s);
for(i=0; i<len; i++){
int v = s[i] - 'a';
if(!ch[u][v]){
memset(ch[nz],0,sizeof(ch[nz]));
val[nz] = 0;
ch[u][v] = nz ++;
}
u = ch[u][v];
val[u] = 0;
}
val[u] = 1;
} void getFail(){
int i,j,n;
queue<int> Q;
while(!Q.empty())
Q.pop();
f[0] = 0;
for(int c =0; c<26; c++){
int u = ch[0][c];
if(u){
f[u] = 0;
last[u] = 0;
Q.push(u);
}
}
while(!Q.empty()){
int r = Q.front();
Q.pop();
for(int c=0; c<26; 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 find(){
int i,j,len = strlen(T),u = 0;
for(i=0; i<len; i++){
int v = T[i] - 'a';
while(u && !ch[u][v]) u = f[u];
u = ch[u][v];
if(val[u]){
found = 1;
return ;
}
else if(last[u]){
found = 1;
return ;
}
}
} int main(){
int i,n;
while(scanf("%d",&n) == 1){
found = 0;
memset(val,0,sizeof(val));
memset(ch[0],0,sizeof(ch[0]));
nz = 1;
for(i=0;i<n;i++){
scanf("%s",s);
insert();
}
scanf("%s",T);
getFail();
find();
if(!found)
printf("NO\n");
else
printf("YES\n");
} return 0;
}