字符串哈希

字符串哈希

题目:AcWing841

首先处理出每个前缀字符串的哈希值

[l,r]的子串的哈希值

如何处理出前缀字符串的哈希值

将这个前缀字符串看做一个P进制的数,将其映射成一个十进制的数(这个数就是hash值)

比如ABCDE的子串ABC这个前缀字符串的哈希值可以映射为(1*P^2 + 2*P^1 + 3*P^0) mod Q (一定要从1开始映射)
在做映射的时候P要取13113331,Q要取2^64,c++中用unsigned long long就可以不用mod Q了,因为溢出就相当于mod

可以预处理出来每个字符的哈希值和对应的P的幂

p[0] = 1;
for(int i = 1 ; i <= n ; i++)
{
	h[i] = h[i-1] * P + str[i];
	p[i] = p[i-1] * P;
}

[l,r]对应的子串的哈希值

视频12分钟处可以推得[l,r]对应的子串的哈希值为h[r]-h[l-1]*P^(r-l+1)

获得[l,r]子串的哈希值代码

typedef unsigned long long ULL;
ULL get(int l,int r)
{
	return h[r] - h[l-1] *p[r-l+1];
}

代码

可以快速统计出某个字符串[l1,r1][l2,r2]的子串是否相同

#include<iostream>
#include<algorithm>

using namespace std ;

typedef unsigned long long ULL;
const int N = 100010 , P = 131;

int n,m;
char str[N];
ULL h[N],p[N];

ULL get(int l,int r)
{
    return h[r] - h[l-1]*p[r-l+1];
}

int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",str + 1);
    
    p[0] = 1;
    for(int i = 1 ; i <= n; i ++)
    {
        h[i] = h[i-1] * P + str[i];
        p[i] = p[i-1] * P;
    }
    
    while(m --)
    {
        int l1,r1,l2,r2;
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        
        if(get(l1,r1) == get(l2,r2)) puts("Yes");
        else puts("No");
    }
    
    return 0;
}
posted @ 2022-08-06 15:33  r涤生  阅读(27)  评论(0编辑  收藏  举报