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