codeforces 514C 字符串哈希/字典树
n个字符串
m次询问,
每次询问,想知道是否在n个字符串中存在一个恰好有一个位置不同的字符串
做法:
1.字符串哈希,如果单纯用ull自然溢出,会被卡碰撞,然后wa27,需要自定义一个模数
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;//head
const int maxn=1e6+10,maxm=2e6+10;
const ll INF=0x3f3f3f3f,mod=1e9+7;
int casn,n,m,k;
const ull decm=257;
unordered_set<ull> vis;
class strhash{public:
ull pw[maxn],hs[maxn],len;
void init(int n=maxn-5){pw[0]=1;rep(i,1,n) pw[i]=pw[i-1]*decm%mod;}
void calhs(string &s,int n){len=n;rep(i,0,len-1)hs[i+1]=(hs[i]*decm+s[i])%mod;}
inline ull geths(int a,int b){return b<a?0:(hs[b]-(hs[a-1]*pw[b-a+1])%mod+mod)%mod;}
inline ull update(int pos,char x){return ((geths(1,pos-1)*decm+x)%mod*pw[len-pos]%mod+geths(pos+1,len))%mod;}
}table;
int main() {IO;
table.init();
cin>>n>>m;
rep(i,1,n){
string s;cin>>s;
table.calhs(s,(int)s.size());
vis.insert(table.hs[s.size()]);
}
rep(i,1,m){
string s;cin>>s;
int len=s.size();
table.calhs(s,len);
int flag=0;
rep(i,0,len-1) rep(j,'a','c')
if(j!=s[i]&&vis.count(table.update(i+1,j))){flag=1;break;}
if(flag) cout<<"YES\n";
else cout<<"NO\n";
}
}
2.字典树上dfs一下就行,注意剪枝
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;//head
const int maxn=5e6+10,maxm=2e6+10;
int casn,n,m,k;
const int csize=4,minc='a';
class trie{public:
#define nd node[now]
struct tnode{char cnt;int son[csize];}node[maxn];
int sz;
void init(int n=maxn-5){memset(node,0,sizeof node);sz=1;}
void insert(string &s,int len){
int now=1;
rep(i,0,len-1){
int ch=s[i]-minc;
if(!nd.son[ch]) nd.son[ch]=++sz;
now=nd.son[ch];
}
nd.cnt=s[len-1];
}
int find(string &s,int now,int cnt,int len,int mxlen){
if(len==mxlen||cnt>1) return cnt==1&&nd.cnt;
int x=s[len]-'a';
rep(i,0,2){
if(!nd.son[i]) continue;
int flag=find(s,nd.son[i],cnt+(i!=x),len+1,mxlen);
if(flag) return 1;
}
return 0;
}
}tree;
int main() {IO;
cin>>n>>m;
rep(i,1,n){
string s;cin>>s;
tree.insert(s,s.size());
}
rep(i,1,m){
string s;cin>>s;
if(tree.find(s,1,0,0,(int)s.size())) cout<<"YES\n";
else cout<<"NO\n";
}
}

浙公网安备 33010602011771号