兔子的兔子(字符串hash)

把我坑惨了(1个小时)cin换成scanf cout 换成printf就过了,
思路:询问区间值就用前缀和来做,将字符串通过一个hash函数映射在几乎不会重复的集合内,能够快速判断是否子字符串是否重复出现过,

  • unsigned long long存hash值相当于自动对 2 64 2^{64} 264mod
  • 把字符串看成P进制下的数,如S="abc" h ( S ) = 1 ∗ p 2 + 2 ∗ p 1 + 3 ∗ p 0 h(S)=1*p^2+2*p^1+3*p^0 h(S)=1p2+2p1+3p0
  • 在S后添加一个charc h ( s + c ) = h ( s ) ∗ p + ( c − ′ a ′ + 1 ) h(s+c)=h(s)*p+(c-'a'+1) h(s+c)=h(s)p+(ca+1)同理char c换成string
  • h ( s + t ) = h ( s ) ∗ p t . s i z e ( ) + h ( t ) h(s+t)=h(s)*p^{t.size()}+h(t) h(s+t)=h(s)pt.size()+h(t) 就是进制进位计算,理解很简单
  • 注意 计算区间子串hash值时,保证p进制的位是相同的然后在相减。
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=1000005;
char str[maxn];
unsigned long long sum[maxn],f[maxn];
int main(){
    freopen("a.txt","r",stdin);
    scanf("%s",str+1);
    int len=strlen(str+1);
    int  m;
    scanf("%d",&m);
    f[0]=1;
    for(int i=1;i<=len;i++){
        sum[i]=sum[i-1]*131+(str[i]-'a'+1);
        f[i]=131*f[i-1];
    }
    for(int i=1;i<=m;i++){
        int a,b,c,d;
        scanf("%d %d %d %d",&a,&b,&c,&d);
        if( sum[b]-sum[a-1]*f[b-a+1] == sum[d]-sum[c-1]*f[d-c+1]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值