一、从1到i的hash值:
注意:
1.hash值最好开到unsigned long long,定义的hash数值要为质数且尽可能大,例如:1311,2333,19260817。
2.hash如果用到map判断应该开成unordered_map<LL, int>vis;
题目:
2019年CSUST省赛选拔赛J题:
一个字符串hash题,用来说明从1~i求hash值的模板:
#include<bits/stdc++.h>
#define N 2000005
#define P 2333
#define LL long long
using namespace std;
int k,len,num;
LL has,ans;
string s;
unordered_map<LL, int>vis;
int main()
{
scanf("%d",&k);
while(cin>>s)//有空格的字符串这样处理
{
num=0;
has=0;
len=s.length();
for(int i=0;i<len;i++)
{
if(i==len-1)
{
has=has*P+(s[i]-'a'+1);//尽量不能有0,因为0001根0100的hash值是一样的
//重点!!!!!!!!!!!!!!!!!!!!!!!!
if(!vis[has])
{
vis[has]=1;
ans++;
}
}
else
{
if(num<k)
{
num++;
has=has*P+(s[i]-'a'+1);
if(num==k)
{
if(!vis[has])
{
vis[has]=1;
ans++;
}
break;
}
}
}
}
}
printf("%lld",ans);
return 0;
}
从l~r的模板见这个题目:
#include<bits/stdc++.h>
#define ull unsigned long long
//一般hash都最好开到usigned long long
#define N 100010
using namespace std;
const ull P=1311;
char a[N],b[N];
int n,lena,lenb,l,r,ans=-1;
ull c[N],hasa[N],hasb[N];
bool check(int mid)
{
int num=0;
for(int i=1;i<=lena-mid+1;i++)
{
ull k=hasa[i+mid-1]-hasa[i-1]*c[mid];
//这一步是关键公式当前的hash[r]-hash[l-1]*c[len],c已经被预处理出来了
//重点!!!!!!!!!!!!!!!!!!!!
if(k==hasb[mid])
{
num++;
if(num>=n)return 1;
}
}
return 0;
}
int main()
{
fgets(a,N,stdin);
fgets(b,N,stdin);
scanf("%d",&n);
c[0]=1;
for(int i=1;i<=N;i++)
c[i]=c[i-1]*P;//求l~r的hash值需要
lena=strlen(a);
hasa[0]=0;
for(int i=0;i<lena;i++)
hasa[i+1]=hasa[i]*P+a[i];
lenb=strlen(b);
hasb[0]=0;
for(int i=0;i<lenb;i++)
hasb[i+1]=hasb[i]*P+b[i];
l=1;r=lenb;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))
{
l=mid+1;
ans=mid;
}
else r=mid-1;
}
if(ans==-1)printf("IMPOSSIBLE");
else
{
for(int i=0;i<ans;i++)
printf("%c",b[i]);
}
return 0;
}