http://www.lydsy.com/JudgeOnline/problem.php?id=4327
对于小串建AC自动机
原串在AC自动机上匹配
对于一个点可以匹配到,那么它的fail指针也可以匹配到
做完以后,按bfs序倒着转移一下标记
如何对于小串进行查询
#include<cstdio>
#include<queue>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
#define ROF(i,s,t) for(register int i=s;i>=t;--i)
const int N=10000011,M=100011;
char S[N];
char A[M][101];
int xu[N];
int n,m,tot;
namespace AC_automaton{
int go[128];
struct Tire{
int fail;
int vis;
int to[4];
}tr[N];
inline void insert(char *s){
int u=0;
for(register int i=0;s[i]!=‘\0‘;++i){
if(!tr[u].to[go[(int)s[i]]])
tr[u].to[go[(int)s[i]]]=++tot;
u=tr[u].to[go[(int)s[i]]];
}
}
inline void build_fail(){
std::queue<int>q;
int v,u,now;
FOR(i,0,3)
if((v=tr[0].to[i]))
q.push(v);
while(!q.empty()){
now=q.front();
xu[++xu[0]]=now;
q.pop();
FOR(i,0,3){
v=tr[now].to[i];
u=tr[now].fail;
if(v){
tr[v].fail=tr[u].to[i];
q.push(v);
}
else
tr[now].to[i]=tr[u].to[i];
}
}
}
inline void match(char *s){
int now=0;
for(register int i=0;i<n;++i){
now=tr[now].to[go[(int)s[i]]];
tr[now].vis=1;
}
}
inline int query(char *s){
int u=0,pos=0;
for(register int i=0;s[i]!=‘\0‘;++i){
u=tr[u].to[go[(int)s[i]]];
if(tr[u].vis)
pos=i+1;
}
return pos;
}
}
using namespace AC_automaton;
int main(){
go[‘E‘]=0;go[‘S‘]=1;go[‘W‘]=2;go[‘N‘]=3;
scanf("%d%d\n",&n,&m);
scanf("%s",S);
FOR(i,1,m){
scanf("%s",A[i]);
insert(A[i]);
}
build_fail();
match(S);
ROF(i,xu[0],1)tr[tr[xu[i]].fail].vis|=tr[xu[i]].vis;
FOR(i,1,m)
printf("%d\n",query(A[i]));
return 0;
}