// 字符串哈希原理
// 举例:
将字符串 s="abcd"视为26进制整数,
hash(s)=1*26^3+2*26^2+3*26^1+4*26^0;
如果字符串很长,h(s)很容易超出 long long 值;
所以: hash(s)%h;(h和26互质&&h尽可能大)
/*-----------------------------------------------------*/
// 注:
一般来说:进制取 131,13331,模取 2^64
(long long 范围:2^63-1,所以应该用unsigned long long )
/*------------------------------------------------------*/
//模板:
1,前缀和思想计算哈希
h[i-1] -> 1~i-1的哈希值
h[i]=h[i-1]*b+(s[i]-'a'+1);
2,计算区间哈希
s=123456789
h[6]=123456 h[r]
h[4]=1234 h[l-1]
h[5,6]=h[6]-h[4]*10^2; h[l,r]=h[r]-h[l-1]*b^(r-(l-1));
/*-------------------------------------------------------*/
1915-【基础】子串判重
来源: 东方博宜oj oj.czos.cn
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int N=1e6+10,P=131;
//h[i]:1~i区间中子串的哈希值
// p[i]:P的i次方
ULL h[N],p[N];
char s[N];
int m;
// 返回字符串子区间的哈希值(计算区间哈希)
ULL get(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
int main()
{
scanf("%s",s+1);
//计算h[]和p[]的值
p[0]=1;
int len=strlen(s+1);
// 计算哈希
for(int i=1;i<=len;i++)
{
p[i]=p[i-1]*P;
h[i]=h[i-1]*P+(s[i]-'a'+1);
}
scanf("%d",&m);
int l1,r1,l2,r2;
while(m--)
{
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
//如果两个子区间的哈希值相同
if(get(l1,r1)==get(l2,r2)) printf("Yes\n");
else printf("No\n");
}
return 0;
}
字符串哈希模板+子串判重---字符串哈希
于 2023-02-13 16:42:04 首次发布