1. 程式人生 > >P3370 【模板】字串雜湊(Hash詳解)

P3370 【模板】字串雜湊(Hash詳解)

題目連結

題意:

給定N個字串(第i個字串長度為Mi,字串內包含數字、大小寫字母,大小寫敏感),請求出N個字串中共有多少個不同的字串。

單hash——模數19260817(80分)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std; 
const long long base=233;//進位制數:1、大於所有字元對應的數字的最大值;2、質數 
const long long mod=19260817;//大質數(很關鍵) 
char s[100005]; long long f[100005]; int n; long long hash(char s[]) { long long ans=0; for(int i=0;i<strlen(s);i++) { ans=(ans*base+(long long)s[i])%mod;//雜湊其實就是把一個數轉化為一個值,注意在存入的時候取模 } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s); f[i]=hash(s); } sort
(f+1,f+n+1); int ans=1; for(int i=2;i<=n;i++) { if(f[i]!=f[i-1]) ans++; } cout<<ans<<endl; }

單hash——模數202370440130137957(AC) 推薦使用這種做法,一是簡潔好寫,二是誤差小,三是時間快(100ms)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std; 
const
long long base=233; const long long mod=212370440130137957ll;//記住這個數字 char s[100005]; long long f[100005]; int n; long long hash(char s[]) { long long ans=0; for(int i=0;i<strlen(s);i++) { ans=(ans*base+(long long )s[i])%mod; } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s); f[i]=hash(s); } sort(f+1,f+n+1); int ans=1; for(int i=2;i<=n;i++) { if(f[i]!=f[i-1]) ans++; } cout<<ans<<endl; }

雙hash——模數19260817、19660813(AC) 時間較慢,有可能卡掉

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std; 
const long long base=233;
const long long mod1=19260817;
const long long mod2=19660813;//雙雜湊,模數取兩個互質大質數 19260817,19660813 
char s[100005];
struct node
{
	long long x,y;
}f[100005];
int n;
long long hash1(char s[])
{
	long long ans=0;
	for(int i=0;i<strlen(s);i++)
	{
		ans=(ans*base+(long long)s[i])%mod1;
	}
	return ans;
}
long long hash2(char s[])
{
	long long ans=0;
	for(int i=0;i<strlen(s);i++)
	{
		ans=(ans*base+(long long)s[i])%mod2;
	}
	return ans;
}
bool cmp1(node a,node b)
{
	return a.x<b.x;
}
bool cmp2(node a,node b)
{
	return a.y<b.y;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		f[i].x=hash1(s);
		f[i].y=hash2(s);
	}
	sort(f+1,f+n+1,cmp1);
	sort(f+1,f+n+1,cmp2);//?
	int ans=1;
	for(int i=2;i<=n;i++)
	{
		if(f[i].x!=f[i-1].x || f[i].y!=f[i-1].y) ans++;
	}
	cout<<ans<<endl; 
}