、## 一串字符串哈希值的计算
题意:给你一个字符串s和m,求出字符串中至少出现m次的最长子串.如果有多解,输出最长字符串的长度以及它出现的最大位置.
分析:其实本题可以用后缀数组来解.下面用哈希值来做.详见刘汝佳训练指南P225
x相当于 base
一般用的x有23 233 2333
mod也是认为设定的值 1e9+7 、 1e9+9
首先对于一个长为n的字符串,我们定义它的哈希值为(下面的x值是人为设定的一个值):
s[0]+s[1]*x+s[2]*x^2+…s[n-1]*x^(n-1)
那么它的每个后缀[i,n-1]的哈希值为H[i]:
s[i]+s[i+1]*x+…s[n-1]*x^(n-1-i)
由上可以得到递推关系:
H[n]=0;
H[i]=H[i+1]*x+s[i]
那么对于该串s中的任意一段的哈希值为hash[i,L]:
hash[i,L]=s[i]+s[i+1]*x+s[i+2]*x^2+…s[i+L-1]*x^(L-1)=H[i]-H[i+L]*x^L
---------------------
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;//与long long 的区别 可以防止 long long
string s,str;
int mod = 1e9+9;
int base = 2333;
const int maxn = 1e6+100;
ull hashes[maxn];//1--i个的哈希值
ull p[maxn]; // p[i]=base^i
ull gethash(int l,int r)//得到l---r的哈希值
{
//r-l+1==字符串l--r的长度
return (hashes[r]-hashes[l-1]*p[r-l+1])%mod;
}
//大数的求余 对于很大的数 只能用字符串存储
string s
int ans = 0;
for(int i=0;i<s.size();i++)
{
ans=(ans*10+s[i]-'0')%mod;
}
上诉函数等价于 1234 % mod === (((((1*10+2)%mod)*10+3)%mod)*10+4)%mod
//哈希值的算法
//一、这个是为了方便计算某一段长度的hash
string s;
int len = s.size();
p[0]=1;
for(int i=1;i<=len;i++)
{
hashes[i]=(hash[i-1]*base+s[i])%mod;//这里的base 相当于 上诉的函数大数求余的10
p[i]=p[i-1]*base%mod;//这p[i]=base^i%mod
}
//二、求某一个字符串的hash
ull ans=0;
for(int i=0;i<s.length();i++)
{
ans = (ans * base + s[i])%mod;
}
return ans;
//ans==这个字符串的hash