字符串哈希

字符串哈希

如果不懂什么是字符串哈希,那么你可以看yxc大佬的视频
算法竞赛进阶指南1.4-1.5哈希与字符串
题目:兔子与兔子
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000100;
#define ULL unsigned long long
ULL h[maxn], p[maxn];
char str[maxn];
int main(){
    scanf("%s", str+1);
    int n = strlen(str+1), q;
    scanf("%d", &q);
    p[0] = 1;
    for(int i = 1; i <= n; i++){
        h[i] = h[i-1] * 131+(str[i] - 'a' + 1);
        p[i] = p[i-1] * 131;
    }
    for(int i = 1; i <= q; i++){
        int l_1, r_1, l_2, r_2;
        scanf("%d %d %d %d", &l_1, &r_1, & l_2, &r_2);
        if(h[r_1]-h[l_1-1]*p[r_1-l_1+1] == h[r_2]-h[l_2-1]*p[r_2-l_2+1]){
            printf("Yes\n");
        }
        else {
            printf("No\n");
        }
    }
return 0;
}

题目:回文子串的最大长度
题意:给你一个字符串,问你这个字符串最大的回文串是多长?
题解:字符串哈希+二分查找
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2001000;//注意数组开的范围
typedef unsigned long long ULL;
char s[maxn];
ULL hr[maxn], hl[maxn], p[maxn];
int base = 131;
ULL query(ULL h[], int l, int r)
{
    return h[r] - h[l-1]*p[r-l+1];
}
int main()
{
    int ca = 0;
    while(scanf("%s", s+1) && strcmp(s+1, "END"))
    {
        int n = strlen(s+1);
        n *= 2;
        for(int i =  n; i > 0; i -= 2) //强行在数组中加入新的辅助符号
        {
            s[i] = s[i/2];
            s[i-1] = 'z'+1;
        }
        p[0] = 1;
        for(int i = 1, j = n; i <= n; i++, j--) //字符串哈希
        {
            hl[i] = hl[i-1]*base + (s[i]-'a'+1);
            hr[i] = hr[i-1]*base +(s[j]-'a'+1);
            p[i] = p[i-1]*base;
        }
        int res = 0;
        int l, r;
        for(int i = 1; i <= n; i++)
        {
            l = 0, r = min(i-1, n-i);
            while(l < r)
            {
                int mid = (l+r+1)>>1;
                if(query(hl, i-mid, i-1) != query(hr, n-(i+mid)+1, n-(i+1)+1))r = mid-1;
                else l = mid;
            }
            if(s[i-l] <= 'z')res = max(res, l+1);
            else res = max(res, l);
        }
        printf("Case %d: %d\n", ++ca, res);
    }

    return 0;
}

题目:后缀数组

思想:字符串哈希+二分查找
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 301000;
typedef unsigned long long ULL;
ULL p[maxn], h[maxn];
char s[maxn];
int vis[maxn], base = 131, n;
ULL get(int l, int r){
    return h[r] - h[l-1]*p[r-l+1];
}
int Binary_Search(int a, int b){
    int l = 0, r = min(n-a+1, n-b+1);
    while(l < r){
        int mid = (l+r+1)>>1;
        if(get(a, a+mid-1) != get(b, b+mid-1))r = mid-1;
        else l = mid;
    }
    return l;
}
bool cmp(int a, int b){
     int l = Binary_Search(a, b);
     int a_val = a+l > n ? INT_MIN : s[a+l];
     int b_val = b+l > n ? INT_MIN : s[b+l];
     return a_val < b_val;
}
int main(){
    scanf("%s", s+1);
    n = strlen(s+1);
    p[0] = 1;
    for(int i = 1; i <= n; i++){
        h[i] = h[i-1]*base+(s[i]-'a'+1);
        p[i] = p[i-1]*base;
        vis[i] = i;
    }
    sort(vis+1, vis+1+n, cmp);
    for(int i = 1; i <= n; i++){
       printf("%d ", vis[i]-1);
    }
    cout<<endl;
    for(int i = 1; i <= n; i++){
        if(i == 1)printf("0");
        else printf(" %d", Binary_Search(vis[i], vis[i-1]));
    }
    cout<<endl;
return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值