地址:https://www.acwing.com/problem/content/843/
关于字符串哈希:
进制哈希。即把每个字符串按进制得出对应的数字。根据y总的模板,进制P取131可以很好地降低冲突概率
假设不出现冲突,那么每个子串,唯一对应一个P进制的哈希值。
先前缀处理一下所有前缀的哈希值。
那么对于[L,R],已知[1,R]和[1,L]的哈希值,需要求[L,R]的哈希值。
假设有:
ABCDEFGH
求[6,8]==FGH的哈希值
推导过程:
ABCDEFGH
ABCDE
它俩之间差三个字符(8-6+1)
那么ABCDE*P^(8-6+1),就是ABCDE000,
两者一减,就是FGH的哈希值了。
即:h[R]-h[L-1]*P^(R-L+1)
h[i]=h[i-1]*P+s[i]
h负责存前缀哈希
p[]负责存次放数
#include<cstdio> #include<cstring> #include<vector> #include<set> #include<algorithm> #include<iostream> #include<vector> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn=1e5+10,maxn2=31*maxn; const int P= 131; ull h[maxn],p[maxn]; char s[maxn]; int n,m; void init() { for(int i=1;i<=n;i++) { p[i]=p[i-1]*P; h[i]=h[i-1]*P+s[i]; } } ull check(int l,int r) { return h[r]-h[l-1]*p[r-l+1]; } int main() { p[0]=1; scanf("%d%d%s",&n,&m,s+1); init(); while(m--) { int l1,r1,l2,r2; scanf("%d%d%d%d",&l1,&r1,&l2,&r2); if(check(l1,r1)==check(l2,r2)) cout<<"Yes"<<endl; else cout<<"No"<<endl; } }