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; } /** */
当初的梦想实现了吗,事到如今只好放弃吗~