兔子的兔子(字符串hash)

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

  • unsigned long long存hash值相当于自动对$2^{64}$mod
  • 把字符串看成P进制下的数,如S="abc" $h(S)=1p^2+2p^1+3*p^0$
  • 在S后添加一个charc $h(s+c)=h(s)*p+(c-‘a’+1)$同理char c换成string
  • $h(s+t)=h(s)*p^{t.size()}+h(t)$ 就是进制进位计算,理解很简单
  • 注意 计算区间子串hash值时,保证p进制的位是相同的然后在相减。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #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;
    }


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!