P3370 字符串哈希(模板)

题目链接

题目大意:给定N个字符串(第i个字符串长度为Mi,字符串内包含数字、大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串。N<=10000,Mi≈1000,Mmax<=1500。

分析:这题的数据很小,map,set之类的都是可以做的,但这里主要是讲一些哈希。

哈希其实就是将一个字符串映射成一个值,并且要让这些值不能大概率地重复,通过哈希的方式来替代一些很费时间的操作。

例如此题,对于每一个字符串,我们通过一个固定的转换方式,使得相同的字符串映射的那个值相同,而不同的字符串尽量不同。

它的方法是选取一个恰当的进制,将字符串的每一个字符看成是这个进位下的一位数字,最终得到的值就是这个字符串的哈希值,通过对比每个字符串的哈希值判断这两个串是否相同。

为什么不能直接直接用每个字符串的ASCII码之和作为这个映射值了,比如ab和ba,显然不是同一个字符串,但是如果这样做,就认为是相同的了,这叫做Hash冲突,所以我们所选择的进制就很重要了,一般是选择大于所有字符对应的数字的最大值,然后mod一个很大的素数。当然也可以用两种甚至多种方式哈希,然后比对每一种哈希值是否相同,这种准确度就非常高了,但是相应的,这也增加了空间复杂度和时间复杂度。

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int maxn =1e4+7;
ull mod=212370440130137957ll;//质数
ull base=131;
int prime=233317;
ull a[maxn];
char s[maxn];

ull Hash(char str[])
{
    int len=strlen(str);
    ull ans=0;
    for(int i=0;i<len;i++)
        ans=(ans*base+(ull)str[i])%mod+prime;
    return ans;
}

int main()
{
    int N,ans=1;
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%s",s);
        a[i]=Hash(s);
    }
    sort(a+1,a+1+N);
    for(int i=1;i<N;i++)
    {
        if(a[i]!=a[i+1])
            ans++;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41311604/article/details/81592020