BZOJ 4327
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; }