哈希冲突.

知识点

哈希冲突

哈希冲突是利用哈希函数时,对哈希值取模(哈希值往往很大,免不了取模),出现了哈希值重复的情况,这样会导致程序出现差错。
经过科学的计算,执行一次哈希函数的错误率为20%!这样的错误率是不容小觑的。

双哈希

我们可以通过双哈希来解决这个问题
所谓双哈希,就是进行两遍哈希,换一下底数和模数,这样可以讲哈希函数的错误率降低到0.001%
这样哈希冲突就很难发生了
温馨提示:底数最好使用与涉及字符数量相近的数,如:全是任意字符,底数可以选128,131等,模数最好是大质数,如:1e9+7,998244353等)

例题

题目:不同子串

时间限制:2秒 内存限制:256M

题目描述

给你一个仅由小写字母组成的长度为 n 的字符串,问你其中有多少个不同的长度为 L 的子串。

输入样例

10 2
abababbabc

输出样例

4

数据范围

对于 100% 的数据, 1 ≤ L ≤ N ≤ 10 ​ 6 ​​ 1≤L≤N≤10​^6​​ 1LN106​​

不同子串题解

思路

字符串比较太慢了,可以转成哈希值进行计算,哈希值会很大,所以只能用双哈希加取模。
首先求出前缀哈希值,然后依次求出区间哈希值
再将两次的哈希值存入pair数组中进行排序,排完序后挨个遍历一遍,判断是否重复,不重复ans+1
最后输出答案

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1000005;
ll n,l,k,cnt;
string s;
pair<ll,ll> p[N];
ll ans;
struct hash{
	ll sed,mod,h[N],pw[N];
	void init(int sed_in,int mod_in){
		sed=sed_in,mod=mod_in;
		pw[0]=1;
		for(int i=1;i<N;i++){
			pw[i]=pw[i-1]*sed%mod;
		}
	}
	void make(string s){
		h[0]=s[0]%mod;
		for(int i=1;i<s.size();i++){
			h[i]=(h[i-1]*sed%mod+s[i])%mod;
		}
	}
	ll get(ll l,ll r){
		return (h[r]-h[l-1]*pw[r-l+1]%mod+mod)%mod;
	}
}s1,s2;
int main(){
	cin>>n>>l>>s;
	s1.init(128,1e9+7);
	s2.init(131,998244353);
	s=" "+s;
	s1.make(s);
	s2.make(s);
	for(int i=1;i<=1+n-l;i++){
		cnt++;
		p[cnt].first=s1.get(i,i+l-1);
		p[cnt].second=s2.get(i,i+l-1);
	}
	sort(p+1,p+1+cnt);
	for(int i=1;i<=cnt;i++){
		if(i==1||p[i]!=p[i-1]){
			ans++;
		}
	}
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值