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

    题目链接:https://www.luogu.org/problem/P3370

    哈希本身是很简单的,单考的概率也非常低,基本都是结合到其他题目中的一个小知识点,就像离散化一样。

    哈希做法是固定的:

    首先设一个进制数base,并设一个模数mod

    而哈希其实就是把一个数转化为一个值,这个值是base进制的,储存在哈希表中,注意一下在存入的时候取模一下即可

    这里介绍三种哈希方法:

    自然溢出哈希:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ull;
    ull base=131;
    ull a[10010];
    char s[10010];
    int n,ans=1;
    ull hashs(char s[])
    {
        int len=strlen(s);
        ull ans=0;
        for (int i=0;i<len;i++)
            ans=ans*base+(ull)s[i];
        return ans&0x7fffffff;
    }
    main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s);
            a[i]=hashs(s);
        }
        sort(a+1,a+n+1);
        for (int i=2;i<=n;i++)
            if (a[i]!=a[i-1])
                ans++;
        printf("%d
    ",ans);
    }

    最稳妥的办法是选择两个10^9级别的质数,只有模这两个数都相等才判断相等,但常数略大,代码相对难写,目前暂时没有办法卡掉这种写法(除了卡时间让它超时)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ull;
    ull base=131;
    struct data
    {
        ull x,y;
    }a[10010];
    char s[10010];
    int n,ans=1;
    ull mod1=19260817;
    ull mod2=19660813;
    ull hash1(char s[])
    {
        int len=strlen(s);
        ull ans=0;
        for (int i=0;i<len;i++)
            ans=(ans*base+(ull)s[i])%mod1;
        return ans;
    }
    ull hash2(char s[])
    {
        int len=strlen(s);
        ull ans=0;
        for (int i=0;i<len;i++)
            ans=(ans*base+(ull)s[i])%mod2;
        return ans;
    }
    bool comp(data a,data b)
    {
        return a.x<b.x;
    }
    main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s);
            a[i].x=hash1(s);
            a[i].y=hash2(s);
        }
        sort(a+1,a+n+1,comp);
        for (int i=2;i<=n;i++)
            if (a[i].x!=a[i-1].x || a[i-1].y!=a[i].y)
                ans++;
        printf("%d
    ",ans);
    }

    如果能背过或在考场上找出一个10^18级别的质数(Miller-Rabin),也相对靠谱,主要用于前一种担心会超时

    这是只用一个10^18质数的hash(100)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ull;
    ull base=131;
    ull a[10010];
    char s[10010];
    int n,ans=1;
    ull mod=212370440130137957ll;//是质数!!
    ull hashs(char s[])
    {
        int len=strlen(s);
        ull ans=0;
        for (int i=0;i<len;i++)
            ans=(ans*base+(ull)s[i])%mod;
        return ans;
    }
    main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s);
            a[i]=hashs(s);
        }
        sort(a+1,a+n+1);
        for (int i=2;i<=n;i++)
            if (a[i]!=a[i-1])
                ans++;
        printf("%d
    ",ans);
    }
  • 相关阅读:
    文件和文件夹权限
    CentOS 8修改用户密码
    Linux新建用户默认设置
    二、工具类
    一、MyBatis 核心配置文件
    十一、容器总结
    十、Collections工具类
    九、集合与数组之间的转化
    八、TreeSet
    ※大神※
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11383430.html
Copyright © 2011-2022 走看看