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

  

posted @ 2017-12-11 17:17  Stump  阅读(131)  评论(0编辑  收藏  举报