codeforces 514C 字符串哈希/字典树

时间:2022-12-30 13:12:42

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