• P3370 【模板】字符串哈希


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

    题目描述

    如题,给定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个不同的字符串

    思路:就是Hash的板子题,注意的是我们可以把 模数 当做无穷大 ,也就是unsigned long long 的最大值,想当于让它爆掉,此时我们会得到一个ull范围内的数

    把它利用字典树的思想存起来,判断是否已经出现过就行了

    看代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<stack>
    #include<cstdlib>
    #include<queue>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ull;
    const LL mod=19260817;
    const LL INF=1e9+7;
    const ull base=2333;
    const int maxn=1e4+50;
    int cnt=0,sum=0;
    struct TridNode
    {
        int son[10];
        bool f1;
    }t[maxn*64];//开这么大是因为 最多有10000个数 每个数最多64位
    ull Cal_hash(string s)
    {
        ull has=0;
        int len=s.size();
        for(int i=0;i<len;i++)
        {
            has=has*base+s[i];//没有模数是因为我们可以看成mod 是ull最大的范围 让它爆掉也无所谓
        }
        return has;
    }
    void Insert(ull x)
    {
        int u=0;
        while(x)
        {
            int c=x%10;x=x/10;
            if(!t[u].son[c]) t[u].son[c]=++cnt;
            u=t[u].son[c];
        }
        if(!t[u].f1)
        {
            t[u].f1=true;
            sum++;
        }
    }
    int main()
    {
        int N;scanf("%d",&N);
        string s;
        for(int i=0;i<N;i++)
        {
            cin>>s;
            ull x = Cal_hash(s);
            Insert(x);//字典树 判断这个数是否存在
        }
        printf("%d
    ",sum);
        return 0;
    }
    /**
    */

    下面给出一种双Hash的解法,顾名思义,就是给出两个Hash值,两个Hash值都相等的话,才把对应的两个字符串判断为相等

    看代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<stack>
    #include<cstdlib>
    #include<queue>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ull;
    const ull Mod1=998244353;
    const ull Mod2=1000000007;
    const LL INF=1e9+7;
    const ull base=2333;
    const int maxn=1e4+50;
    int cnt=0,sum=0;
    struct Two
    {
        ull x,y;
    }a[maxn];
    bool cmp(const Two a1,const Two a2)
    {
        return a1.x<a2.x;
    }
    int p=0;
    ull Cal_hash(string s,ull mod)
    {
        ull has=0;
        int len=s.size();
        for(int i=0;i<len;i++)
        {
            has=(has*base+s[i])%mod;//没有模数是因为我们可以看成mod 是ull最大的范围 让它爆掉也无所谓
        }
        return has;
    }
    int main()
    {
        int N;scanf("%d",&N);
        string s;
        for(int i=0;i<N;i++)
        {
            cin>>s;
            a[p].x = Cal_hash(s,Mod1);
            a[p].y = Cal_hash(s,Mod2);
            p++;
        }
        sort(a,a+p,cmp);
        if(p>0) sum=1;
        for(int i=1;i<p;i++)
        {
            if(a[i].x==a[i-1].x&&a[i].y==a[i-1].y) continue;
            else sum++;
        }
        printf("%d
    ",sum);
        return 0;
    }
    /**
    */
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    margin:0 auto; 为什么会失效
    vue 登录滑块验证
    layui table 添加序号列
    纯css :after 菜单后面添加“<”
    设置div为不可点击
    ubuntu中root用户在图形界面登录
    ubuntu root用户无法登录filezilla的问题
    ubuntu无法用putty登录
    解决ubuntu和windows电脑之间无法复制粘贴问题
    E: Unable to locate package ubuntu
  • 原文地址:https://www.cnblogs.com/caijiaming/p/11870785.html
Copyright © 2020-2023  润新知