字符串哈希用来解决字符串匹配问题。设文本串的长度为(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)
这样可以不断通过右移一位计算子串的哈希值,将所有位置的哈希值与模式串的哈希值比较,完成匹配
也可以预处理字符串所有前缀的哈希值和基数的幂次,设前缀和的哈希值数组为(sum[maxn]),基数的幂次数组为(p[maxn]),则有:(H(S[c+1,cdots,c+k])=sum[c+k]-sum[c]*p[k])
相关题目: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
");
else printf("%d %d
",l,get(l));
}
return 0;
}