字符串算法
哈希
所谓串哈希,就是通过一系列方法把一个字符串转成一个数字,方法类似进制转换,我们把这个数字称为哈希值,比如说字符串 \(s\),我们设 \(H(s)\) 就是它的哈希值,那么 \(H(s)=\sum_{i=0}^{|s|-1}s[i]\) 就是一个非常基本的哈希。
哈希冲突
所谓哈希冲突就是表示不同的字符串得到了相同的哈希值,这样就会是答案错误。所以为了避免哈希冲突,我们一般都会有一个 \(base\),表示一个进制,它一般都会是质数,且比较大,那么我们就需要使用进制转换的方法来求哈希值,\(H(s)=\sum_{i=0}^{|s|}s[i] \times base^i\)。
但是普通的 \(int\) 的范围只有那么大,也就是 \(-2^{31}\)至\(2^{31}-1\),如果需要防止出现负数肯定就是需要一个 \(mod\) 的,但是如果取模就会增加我们的时间复杂度,毕竟取模并不是 \(O(1)\) 的,这是后我们可以在这 \(int\) 的前面加一个 \(unsigned\),我们知道 \(unsigned\ int\) 的存储范围是 \(0\)至\(2^{32}-1\),这样就会自动取模,并且这系统自带的取模还是不需要时间的。
改成代码就是:
ull check(string s,int base){
ull ans=0;
for(auto i:s)ans=ans*base+i;
return ans;
}
但是这样子写哈希,很容易就会放生哈希冲突,而解决哈希冲突的办法很简单,就是使用两个哈希,我们称之为双哈希,顾名思义,就是用两个不同的 \(base\)。
我们知道,判断字符串 \(s_1==s_2\) 的时间复杂度是 \(O(size)\)
但是两个数字 \(s_1==s_2\) 的时间复杂的却是 \(O(1)\)。
所以运用字符串哈希就可以帮助我们减少字符串比较的时间。
hash 数组
我们发现,如果每一个子串都重新计算 \(hash\) 值,是需要计算 $\frac{n^2}{2} $ 个,而我们发现,这个 hash 值其实类似一个前缀和,所以我们对于每一位记下当前的 hash 值(记为 sh数组) ,则可以得到区间 \([l,r]\) 的hash 值就是 \(hs_r-hs_l \times pw_{r-l+1}\)。
可以优化很多空间。

浙公网安备 33010602011771号