【bzoj1819】[JSOI]Word Query电子字典 trie+暴力

先建出trie树,暴力在trie树上dfs,三种情况分别对应字符串跳一下,trie树上跳一次,trie树上往不同方向跳一次,注意记录一下每个节点是否出现过,因为可能有同一个字符串经过不同的操作多次到达的情况。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 200010

using namespace std;

int ch[maxn][26];
bool tag[maxn];
char s[maxn];
int q[maxn];
bool vis[maxn];
int ans,n,m,tot,len,top;
bool w;

void insert()
{
	int len=strlen(s),x=0;
	for (int i=0;i<len;i++)
	{
		if (ch[x][s[i]-'a']==-1) ch[x][s[i]-'a']=++tot;
		x=ch[x][s[i]-'a'];
	}
	tag[x]=1;
}

void dfs(int x,int y,int f)
{
	if (x==len && tag[y] && !f) {w=1;return;}
	if (x==len && tag[y] && f) {if (!vis[y]) ans++,q[++top]=y,vis[y]=1;return;}
	if (x<len && !f) dfs(x+1,y,1);
	if (!f)
	{
		for (int i=0;i<26;i++)
	  	  if (ch[y][i]!=-1) {dfs(x,ch[y][i],1);if (i!=s[x+1]-'a') dfs(x+1,ch[y][i],1);}
	}
	if (x==len) return;
	if (ch[y][s[x+1]-'a']!=-1) dfs(x+1,ch[y][s[x+1]-'a'],f);
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=0;i<=200000;i++)
	  for (int j=0;j<26;j++)
	    ch[i][j]=-1;
	for (int i=1;i<=n;i++)
	{
		scanf("%s",s);
		insert();
	}
	for (int i=1;i<=m;i++)
	{
		ans=0;w=0;
		while (top) vis[q[top--]]=0;
		scanf("%s",s+1);
		len=strlen(s+1);
		dfs(0,0,0);
		if (w) printf("-1\n"); else printf("%d\n",ans);
	}
	return 0;
}


你可能感兴趣的:(【bzoj1819】[JSOI]Word Query电子字典 trie+暴力)