字符串哈希
一、 引入
哈希算法是通过一个哈希函数H,将一种数据(如字符串)转化为另一种数据(通常转化为整形数值),有些题可用map做,但数据一大就要用到字符串哈希
二、字符串哈希
寻找长度为n的主串S中的匹配串T(设长度为m,且m<n)出现的位置或次数属于字符串匹配问题。可以用暴力算法也可以使用KMP算法等等。但这里介绍一下字符串哈希。
字符串哈希就是将每个字符串转化为一个数值、一个独属于该字符串的数值,然后再去遍历主串,判断在主串与匹配串的哈希值是否相等即可,每次判断为O(1)的时间。这样就可以变成O(n)的时间完成判断。那么怎么预处理哈希值呢?
三、哈希方法
哈希的方法可以分为:自然溢出、单哈希、双哈希。
1.自然溢出
自然溢出其实就是用unsigned long long来代替了对质数取余这一步骤,unsigned long long本身范围就是2^64-1,也相当与对一个大质数取余了,其实到了一样。不过因为简单易于实现,最常用这种方法来实现。
先声明hash[maxn]的类型为unsigned long long,哈希函数hash[i]=hash[i-1]*p+s[i]-‘a’+1(s为字符串)
2.单哈希
单哈希是比较经典的哈希方法,hash[i]=(hash[i-1]*p+s[i]-‘a’+1)%mod(p,mod为质数,而且p<mod,p与mod取尽可能大的质数,减少冲突概率)
3.双哈希
顾名思义,用两个哈希数组hash1,hash2和两个mod1,mod2来实现,结果用一个二元组表示
hash1[i]=(hash1[i−1])∗p+s[i]-‘a’+1) % mod1
hash2[i]=(hash2[i−1])∗p+s[i]-‘a’+1) % mod2
hash结果为<hash1[n],hash2[n]>
上述过程中的步骤作用:乘p,相当于把字符串看成一个p进制的数,类比16进制。哈希值就是进制转换之后对mod取余的结果。
四、哈希值代码
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<stack>//栈
#include<queue>//队列
#include<set>//集合
#include<map>//映射
using namespace std;
typedef long long ll;
const int N=100009;
const int p=131;
ll pi[N],h[N];
int main()
{
int n;
string s;
cin>>n>>s;
pi[0]=1;
for(int i=1;i<=n;i++)
pi[i]=pi[i-1]*p;
for(int i=1;i<=n;i++)
h[i]=h[i-1]*p+s[i-1];
return 0;
}
我也是从这位大佬这里找到的灵感:看链接:https://blog.csdn.net/qq_43472263/article/details/99414049