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\n",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\n",sum);
    return 0;
}
/**
*/

 

posted @ 2019-11-16 10:15  执||念  阅读(163)  评论(0编辑  收藏  举报