BZOJ1212

http://www.lydsy.com/JudgeOnline/problem.php?id=1212

建好AC自动机在Trie树上进行DP

dp[i]|=dp[i-tr[tmp].len]

找到dp[1]==1的max{i}

#include<cstdio>
#include<queue>
#include<cstring>
#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=1000011;
std::queue<int>q;
int dp[N];
namespace AC_automaton{
	char s[N];
	char A[N];
	struct Tire{
		int fail;
		int to[26];
		int len;
	}tr[N];
	int tot;
	inline void insert(char *s,int pos){
		int u=0,v;
		for(register int i=1;s[i]!='\0';++i){
			if(!tr[u].to[s[i]-'a'])
				tr[u].to[s[i]-'a']=++tot;		
			u=tr[u].to[s[i]-'a'];
		}
		tr[u].len=strlen(s+1);
	}
	inline void build_fail(){
		int u,v,now;
		FOR(i,0,25)
			if((u=tr[0].to[i])){
				tr[u].fail=0;
				q.push(u);
			}
		while(!q.empty()){
			now=q.front();q.pop();
			FOR(i,0,25){
				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 int match(char *s){
		int now=0,tmp,n=strlen(s+1);
		FOR(i,1,n)dp[i]=0;
		dp[0]=1; 
		int ans=0;
		for(register int i=1;i<=n;++i){
			now=tr[now].to[s[i]-'a'];
			tmp=now;
			while(tmp){
				dp[i]|=dp[i-tr[tmp].len];
				tmp=tr[tmp].fail;
				if(dp[i]){ans=i;break;}
			}
		}
		return ans;
	}
}
using namespace AC_automaton;
int n,m;
int main(){
	scanf("%d%d",&n,&m);
	FOR(i,1,n){
		scanf("%s",s+1);
		insert(s,i);
	}
	build_fail();
	while(m--){
		scanf("%s",A+1);
		printf("%d\n",match(A));
	}
	return 0;
} 

  

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