字符串哈希
字符串哈希用来解决字符串匹配问题。设文本串的长度为\(n\),模式串的长度为\(m\),通过滚动哈希优化可以在\(O(n+m)\)的时间复杂度内完成匹配
选取两个互素常数\(b\)和\(m\),\(b\)可以选择\(131,13331\)等,可以降低哈希冲突的概率,\(m\)通常选择\(2^{64}\),通过自然溢出省去取模运算
哈希函数:\(H(S[c+1,\cdots,c+k])=(H(S[c,\cdots,c+k-1])*b+S[c+k]-S[c]*b^k)\ mod\ m\)
这样可以不断通过右移一位计算子串的哈希值,将所有位置的哈希值与模式串的哈希值比较,完成匹配
也可以预处理字符串所有前缀的哈希值和基数的幂次,设前缀的哈希值数组为\(hash[maxn]\),基数的幂次数组为\(pre[maxn]\),则有:\(H(S[c+1,\cdots,c+k])=hash[c+k]-hash[c]*pre[k]\)
模板:字符串哈希,预处理前缀以及幂次
const int maxn=100010;
const ULL base=131;
char s[maxn];
ULL pre[maxn],hash[maxn];
void init(){
pre[0]=1;
for(ULL i=1;i<=100005;i++) pre[i]=pre[i-1]*base;
}
void Hash(int n){
for(int i=1;i<=n;i++){
hash[i]=hash[i-1]*base+s2[i]-'a'+1;
}
}
ULL getHash(ULL s[],int l,int r){
return s[r]-s[l-1]*pre[r-l+1];
}
相关题目:hdu4080 Stammering Aliens
二分+字符串哈希
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define ull unsigned long long
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=40010;
const ull b=13331;
int m,n;
ull f[maxn],p[maxn];
char s[maxn];
map<ull,int> mp;
bool check(int x){
mp.clear();
ull res;
for(int i=1;i+x-1<=n;i++){
res=f[i+x-1]-f[i-1]*p[x];
mp[res]++;
if(mp[res]>=m) return true;
}
return false;
}
int get(int x){
mp.clear();
int pos=-1;
ull res;
for(int i=1;i+x-1<=n;i++){
res=f[i+x-1]-f[i-1]*p[x];
mp[res]++;
if(mp[res]>=m) pos=i;
}
return pos-1;
}
int main(){
while(scanf("%d",&m)!=EOF && m){
scanf("%s",s+1);
n=strlen(s+1);
f[0]=0;
p[0]=1;
for(int i=1;i<=n;i++){
f[i]=f[i-1]*b+s[i];
p[i]=p[i-1]*b;
}
int l=0,r=n;
while(r>l){
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
if(l==0) printf("none\n");
else printf("%d %d\n",l,get(l));
}
return 0;
}

浙公网安备 33010602011771号