zoukankan      html  css  js  c++  java
  • 字符串哈希

    对于字符串的处理,有很多需要把重复字符串去掉的问题,但是直接比较字符串会出现很多问题。

    例如,我将 "abc","bbb","cba",直接sb的变成数字进行比较,会导致将这三个字符串判断为一样的(233)

    一般智商正常情况下 , 直接比较 判重 需要将字符串一个一个比对, 所以就会浪费大量时间。

    这个时候我们就需要将字符串转化为一定大小的数字来进行储存。这就需要我们来使用hash。

    那么哈希的原理是什么呢?哈希的原理就是将·字符串中每一个字符乘上一个数字(像进制转换那样搞成一个数)(一般是一个质数,具体原因我也不清楚,希望有dalao能在评论里指出来。)

    就是把字符串搞成一个很好的数字放到bool数组里进行判重,

    #include<bits/stdc++.h>
    using namespace std;
    #define X 127
    const int N=10005;
    typedef unsigned long long Ull;
    int n,ans;
    Ull a[N];
    char s[N];
    int HASH(){
    	scanf("%s",s+1);
    	int len=strlen(s+1);
    	int Hash=0;
    	for(int i=1;i<=len;i++){
    	Hash=Hash*X+s[i]-'a',Hash%=127;
    
         }
    	return Hash;
    }
    

      

      至于为什么用unsigned long long 来储存是为了防止字符串太大溢出,使用unsigned long long可以在溢出的情况下大概率保证hash值不同(还是有非酋会撞上相同的情况)。

      然后就可以利用hash值来对比两个字符串是否相等。

      附上几道hash水题

      洛谷3370 模板题

    #include<bits/stdc++.h>
    using namespace std;
    #define X 127
    const int N=10005;
    typedef unsigned long long Ull;
    int n,ans;
    Ull a[N];
    char s[N];
    int HASH(){
    	scanf("%s",s+1);
    	int len=strlen(s+1);
    	int Hash=0;
    	for(int i=1;i<=len;i++){
    	Hash=Hash*X+s[i]-'a';
    	}
    	return Hash;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		a[i]=HASH();
    	}
    	sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++){
    		if(a[i]!=a[i+1])ans++;
    	}
    	printf("%d",ans);
    	return 0;
    }
    

      codevs 2875

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define X 127
    #define mod 999991
    bool a[mod+6];
    int n,m;
    int Hash(){
    	char s[1100];
    	scanf("%s",s+1);
    	int tot=0;
    	int len=strlen(s+1);
    	for(int i=1;i<=len;i++){
    		tot=(tot*X+s[i]-'a')%mod;
    	}
    	return (tot%mod);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		a[Hash()]=1;
    	}
    	scanf("%d",&m);
    	for(int i=1;i<=m;i++){
    		if(a[Hash()])printf("Yes
    ");
    		else printf("No
    ");
    	}
    	return 0;
    } 
    

       还有一道bzoj水题 可以练习hash和平衡树

       bzoj 2761

       hash做法

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define mod 1999
    #define N 50010
    bool Hash[N];
    int cnt,a[N],to[N],n;
    int head[N];
    inline bool judge(int x){
    	if(!Hash[x])return 0;
    	for(int i=head[x];i;i=to[i]){
    		if(a[i]==x)return 1;
    	}
    	return 0;
    }
    inline void insert(int x){
    	Hash[x]=1;
    	a[++cnt]=x;
    	to[cnt]=head[x];
    	head[x]=cnt;
    }
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		cnt=0;
    		memset(head,0,sizeof(head));
    		memset(to,0,sizeof(to));
    		memset(a,0,sizeof(a));
    		scanf("%d",&n);
    		int x=0;
    		for(int i=1;i<=n;i++){
    			scanf("%d",&x);
    			if(judge(x))continue;
    			insert(x);
    			if(i==1)printf("%d",x);
    			else printf(" %d",x);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    /*
    2
    
    11
    
    1 2 18 3 3 19 2 3 6 5 4
    
    6
    
    1 2 3 4 5 6
     */
    

      

     当我们计算两个不同的字符串 有可能凑巧他们的hash值是相等的 ,于是就可以每个字符串算出两个hash值

     附上恶心的双hash代码(看一看找个乐子就行了 ,这种恶心的代码除了J1m没人会写的,还是去学STLmap吧)

    
    
    //输入+双哈希    
        for(int k=1;k<=N;k++,M++)
        {
            char s1[12],s2[12];
            scanf("%s %s",s1,s2);
           long long h3=0,h4=0;
           for(int i=0;i<strlen(s1);i++)h3=(h3*Jin+s1[i])%mod,h4=(h4*Kai+s1[i])%mod;
            if(size[h3])
                for(int i=1;i<=size[h3]+1;i++)
                {
                    if(hash[h3][i][0]==h4){x[M]=hash[h3][i][1];break;}
                    if(i==size[h3]+1){size[h3]++,hash[h3][i][0]=h4,hash[h3][i][1]=++cnt,x[M]=cnt;break;}
                }
            else size[h3]++,hash[h3][1][0]=h4,hash[h3][1][1]=++cnt,x[M]=cnt;     
    
    
    

      

  • 相关阅读:
    centos 创建swap 交换分区
    nginx android app 慢网络请求超时
    使用docker toolbox 在windows上搭建统一环境
    Docker Volume 之权限管理(转)
    一次架构失误的反思
    Cannot connect to the Docker daemon. Is the docker daemon running on this host?
    docker-compose启动报错,解决方案
    php 执行程序分析
    继电器是如何成为CPU的(2)
    [每天默写一个算法]KMP
  • 原文地址:https://www.cnblogs.com/Elfish/p/7537794.html
Copyright © 2011-2022 走看看