字符串哈希
1、字符串哈希
其实就是把每个字符转换成ASCLL码,然后就把这个字符串当成一个某(base)进制的数字,再转换成十进制。
每个数字要乘它的权重(第一个的权重是很多次幂,是通过前缀加循环的方式实现的,而不是直接乘一个高次幂)
1、字符串的哈希值核心板子:
typedef unsigned long long ull; //基本都是无符号数
ull base=131;//都喜欢用这个质数。要么131,要么29
ull prime=233317; //单哈希的辅助数(可以不写)
ull M=212370440130137957ll;//最大的用来取模的数(越大越好的,这个就是最大)
ull hashs(string s)
{
int len=s.size();
ull ans=0;
for (int i=0;i<len;i++)
//自然溢出 ans=ans*base+(ull)s[i];//一般都是用ASCLL码
//单哈希(最常用)ans=(ans*base+(ull)s[i])%M+prime;
//双哈希(正确性最高,感觉出不到这个)就是再弄一个ans,但是换个底数(一般就29和131)
return ans;//如果你想得到各个子串的哈希值,那就要用前缀数组(存ans就行)还是不需要递推
}
//ans即为本字符串的哈希值
2、构造前缀哈希值数组和后缀哈希值数组
全局:
const int N=1e6+5,mod=1e9+7,P=131;//P是底,mod也可以是上面那个M(越大越好)
int n;
int h1[N],h2[N],p[N];//P是记录base数组,用于计算区间哈希值
char s[N];
函数:
void make_hash(){
p[0]=1,h1[0]=0;
for(int i=1;i<=n;i++){
h1[i]=(h1[i-1]*P%mod+s[i])%mod;
p[i]=p[i-1]*P%mod;
}
h2[n+1]=0;
for(int i=n;i>=1;i--){
h2[i]=(h2[i+1]*P%mod+s[i])%mod;
}
}
主函数里要这么写
cin>>s+1;//**直接从1开始输入的,所以这个板子里的下标均从1开始**
n=strlen(s+1);
make_hash();
3、得到一个区间l到r的前缀值
int get1(int l,int r)
{
return (h1[r]%mod-h1[l-1]%mod*p[r-l+1]%mod+mod)%mod;
}
4、得到一个区间l到r的后缀值
int get2(int l,int r)
{
return (h2[l]%mod-h2[r+1]%mod*p[r-l+1]%mod+mod)%mod;
}

浙公网安备 33010602011771号