zoukankan      html  css  js  c++  java
  • Hash(学习笔记)

    写这篇博客仅是为了凑齐神龙,真想学Hash请另寻高明.

    关于哈希Hash,我没有找到什么专门学习它的博客.因为它实在是不太好讲,但实现起来其实是很容易的,它的思想很简单,可是就是不太好阐释,而且它就像离散化一样,一般情况下都用于对数据的预处理.

    反正我对Hash的理解就是,当碰到一些很难处理的数据时(比如字符串、很大的数等等),可以考虑将它通过哈希函数变成一个较小的常数,这个较小的常数就称作哈希值.

    真的不想再用文字来叙述这个东西了

    字符串哈希:(最常用,最重要)

    给出两个仅含大写字母的字符串s1,s2,求s1在s2中出现了多少次.

    unsigned long long power[MAXN],sum[MAXN];
    //unsigned long long
    char s1[MAXN],s2[MAXN];
    int main(){
        power[0]=1;
        for(int i=1;i<=MAXN;i++)
    		power[i]=power[i-1]*b;
    //预处理出b^n,b是一个质数(自行赋值).
        scanf("%s%s",s1+1,s2+1);
        	int n=strlen(s1+1),m=strlen(s2+1);
        for(int i=1;i<=m;i++)
    		sum[i]=sum[i-1]*b+s2[i]-'A'+1;
    //计算主串s2的哈希值
    //这是字符串哈希的精髓,好好理解一下
        unsigned long long s=0;
        for(int i=1;i<=n;i++)
    		s=s*b+s1[i]-'A'+1;
    //计算匹配串s1的哈希值
    //因为我们要计算的是s1在s2中出现的次数,所以是要拿s1
    //整个串的哈希值和s2的部分串的哈希值比较,看是否相等
    //这就是为什么本题中s1的哈希值直接用变量s存,而s2的
    //哈希值要存在一个数组中
    //此外,s1和s2的哈希函数(即哈希值的计算方法)要相同.
        int ans=0;
        for(int i=0;i<=m-n;i++)
    		if(s==sum[i+n]-sum[i]*power[n])
            	ans++;
    //枚举s2的长度等于s1的子串的哈希值,如果相等,ans+1
        printf("%d
    ",ans);
        return 0;
    }
    
    

    哈希表:(真心觉得用得不多)

    (该图是在模16意义下的哈希表):

    【模板】字符串哈希

    题意:给你n个字符串,判断其中不相同的字符串的个数.

    分析:做法很多,我下面的代码是将字符串哈希和哈希表的思想结合起来做的.应该会更有助于全面理解哈希.

    #include<bits/stdc++.h>
    using namespace std;
    
    const int p1=47,p2=79,mod1=1e6+3,mod2=1e6+9;
    //构造两个哈希函数,只有同时满足两个哈希值相等
    //才是相同的字符串,能有效降低哈希冲突的概率.
    int n,tot,ans;
    int nxt[10005],end[10005],head[mod1+5];
    string s[10005];
    
    void insert(int x,int y){
        nxt[++tot]=head[x];
        head[x]=tot;
        end[tot]=y;
    }
    //将一个字符串通过两个哈希函数得到的两个哈希值
    //插入邻接表(哈希表)
    //结合上面那个图来看就是把x当做表头
    //y当做表头后链表上的值
    
    int query(int x,int y){
        for(int i=head[x];i;i=nxt[i]){
            if(end[i]==y) return 1;
        }
        return 0;
    }
    //到哈希表中查询字符串是否存在过
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            cin>>s[i];
            int len=s[i].size();
            int sum1=0,sum2=0;
            for(int j=0;j<len;j++){
                sum1=(sum1*p1+s[i][j])%mod1;
                sum2=(sum2*p2+s[i][j])%mod2;
            }
    //双哈希函数,这里没有让s[i][j]-'a'什么的,
    //是因为字符串可能小写,可能大写,可能是数字,
    //就干脆让它自己强制转换成数字就好了.
            if(query(sum1,sum2)==1) ans++;
            else insert(sum1,sum2);
        }
        printf("%d",n-ans);
        return 0;
    }
    
    
  • 相关阅读:
    Preparing for Merge Sort(二分)
    Polycarp's phone book(unordered_mpa 大法好)
    Yet Another Task with Queens
    nginx 初时
    JSON.stringfiy 序列化
    css grid布局使用
    遍历对象属性5种方法,排列顺序规则
    归并方法
    处理地图经纬度,保留6位小数
    js 操作方法
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10333536.html
Copyright © 2011-2022 走看看