• 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
    ";
        else cout<<"NO
    ";
      }
    }
    

     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
    ";
        else cout<<"NO
    ";
      }
    }
    
  • 相关阅读:
    Java 多线程概述
    Java 线程的创建和启动
    状态模式
    Spring 依赖注入
    Spring IOC
    在JavaEE中使用Mybatis框架
    Active Reports 补空白行
    SpreadForWin 清空Sheet
    日期格式转换
    Select Case 的实现
  • 原文地址:https://www.cnblogs.com/nervendnig/p/11310149.html
Copyright © 2020-2023  润新知