• 字符串哈希hash


    题目描述

    如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字、大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串。

    友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:)

    输入输出格式

    输入格式:

    第一行包含一个整数N,为字符串的个数。

    接下来N行每行包含一个字符串,为所提供的字符串。

    输出格式:

    输出包含一行,包含一个整数,为不同的字符串个数。

    输入输出样例

    输入样例#1:
    5
    abc
    aaaa
    abc
    abcc
    12345
    输出样例#1:
    4

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=10,Mi≈6,Mmax<=15;

    对于70%的数据:N<=1000,Mi≈100,Mmax<=150

    对于100%的数据:N<=10000,Mi≈1000,Mmax<=1500

    样例说明:

    样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。

    Tip: 感兴趣的话,你们可以先看一看以下三题:

    BZOJ3097:http://www.lydsy.com/JudgeOnline/problem.php?id=3097

    BZOJ3098:http://www.lydsy.com/JudgeOnline/problem.php?id=3098

    BZOJ3099:http://www.lydsy.com/JudgeOnline/problem.php?id=3099

    如果你仔细研究过了(或者至少仔细看过AC人数的话),我想你一定会明白字符串哈希的正确姿势的^_^

    字符串hash,把每一位当做一个某进制大数的一位,乘积后mod一个素数 

    在此讲解三种姿势

    1.ull自然溢出

    100分

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

    2.对单素数取mod

    70分

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

    对双素数取mod

    100分

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 101010;
    typedef unsigned long long ull; 
    const int  mod1 = 20020711;
    const int  mod2 = 19260817;
    struct data{
        int x, y;
        bool operator < (const data &a)const {
            return x< a.x;
        }
    }hash[maxn];
    int base=131;
    char s[maxn];
    
    int n,ans=1;
    int h1(char *s) {
        int len =strlen(s);
        int ans=0;
        for(int i=0;i<len;++i)
            ans=(ans*base+s[i])%mod1;
        return ans;
    }
    int h2(char *s) {
        int len =strlen (s);
        int ans=0;
        for(int i=0;i<len;++i)
            ans=(ans*base+s[i])%mod2;
        return ans;
    }
    int main () {
        scanf("%d",&n);
        for(int i=1;i<=n;++i) {
            scanf("%s",s);
            hash[i].x=h1(s);
            hash[i].y=h2(s);
        }
        sort(hash+1,hash+n+1);
        for(int i=2;i<=n;++i)
          if(hash[i].x!=hash[i-1].x||hash[i].y!=hash[i-1].y)
                ans++;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    COM编程-注册DLL形式的COM服务器
    控制台console使用MFC库函数,Cout输出CString的方法
    [C#]窗体切换--避免开启多个线程
    OpenCV配置使用版
    Dependency Walker使用说明
    TCP粘包和半包的处理方法
    GENERATED_UCLASS_BODY 和 GENERATED_BODY 区别
    c++ 的 坑真多之头文件
    Introduction to replication 翻译
    c++ 的 static_cast
  • 原文地址:https://www.cnblogs.com/sssy/p/7674414.html
Copyright © 2020-2023  润新知