Codeforces 514C. Watto and Mechanism解题报告(字典树)
传送门
题意:给你一个字典和一些询问,问你对于每个询问的字符串必须更改一个字符,能否得到字典中的某一个单词。
思路:先构造一颗字典树,然后搜一遍就行了,要注意strlen不能每次都用,常数很大!
#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
using namespace std;
const int maxn=300005,maxm=600005;
int tree[maxm][5],en[maxm];
int n,m,e;
char s[maxm];
bool flag;
bool siz[maxm];
int lenth;
void add_edge(char c[])
{
int len=(int)strlen(c);
int root=0;
rep(i,0,len-1)
{
if(!tree[root][c[i]-'a'])
tree[root][c[i]-'a']=++e;
root=tree[root][c[i]-'a'];
}
en[root]=1;
siz[(int)strlen(c)]=1;
}
void dfs(int root,int x,int pos,int cn)
{
if(flag)return;
//cout<<char(x+'a')<<" "<<pos<<endl;
if(pos>=lenth)
{
return;
}
int cnn=cn;
if(pos==lenth-1 && en[root])
{
//cout<<char(x+'a')<<" "<<pos<<endl;
if((x==s[pos]-'a' && cnn==1) || (x!=s[pos]-'a' && cnn==0))
flag=1;
return;
}
if(pos!=-1)
{
if(s[pos]-'a'!=x)
{
cnn++;
if(cnn>=2)
return;
}
}
int i=0;
if(tree[root][i] && (cnn==0 || (cnn==1 && s[pos+1]-'a'==i)))
{
dfs(tree[root][i],i,pos+1,cnn);
if(flag)
return;
}
i=1;
if(tree[root][i] && (cnn==0 || (cnn==1 && s[pos+1]-'a'==i)))
{
dfs(tree[root][i],i,pos+1,cnn);
if(flag)
return;
}
i=2;
if(tree[root][i] && (cnn==0 || (cnn==1 && s[pos+1]-'a'==i)))
{
dfs(tree[root][i],i,pos+1,cnn);
if(flag)
return;
}
}
int main()
{
scanf("%d%d",&n,&m);
if(n==1 && m==1)
{
string s1,s2;
cin>>s1>>s2;
if(s1.size()!=s2.size())
{
puts("NO");
return 0;
}
int cnt=0;
rep(i,0,s1.size()-1)
{
if(s1[i]!=s2[i])
{
cnt++;
}
if(cnt>=2)
{
flag=1;
break;
}
}
if(flag || cnt==0) puts("NO");
else puts("YES");
return 0;
}
rep(i,1,n)
{
char c[maxm];
scanf("%s",c);
add_edge(c);
}
//cout<<en[0]<<endl;
rep(i,1,m)
{
scanf("%s",s);
lenth=(int)strlen(s);
flag=0;
if(siz[lenth]==0)
{
puts("NO");
continue;
}
dfs(0,0,-1,0);
if(flag) puts("YES");
else puts("NO");
}
return 0;
}