字符串哈希模板(单双哈希)

进制质数:131,13331 ; 取模质数: 1e9 + 7,1e9 + 9

单哈希:靠 ULL 溢出自动取模

#include<bits/stdc++.h>
#include<unordered_map>
#define debug cout << "debug---  "
#define debug_ cout << "\n---debug---\n"
#define oper(a) operator<(const a& ee)const
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define all(a) a.begin(),a.end()
#define sz(a) (int)a.size()
#define endl "\n"
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 1e5 + 10, M = 2e6 + 10, mod = 1e9 + 7;
int INF = 0x3f3f3f3f; ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, B = 10, ki;

ull p[N], P = 131;
ull h[N];

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

char str[N];

void solve() {
    cin >> n >> m;
    cin >> str + 1;

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

    while (m--)
    {
        int l1, r1, l2, r2;
        cin >> l1 >> r1 >> l2 >> r2;
        if (get(l1, r1) == get(l2, r2))cout << "Yes\n";
        else cout << "No\n";
    }
}

signed main() {
    cinios;
    int T = 1;
    for (int t = 1; t <= T; t++) {
        solve();
    }
    return 0;
}
/*
*/
//板子

双哈希:对字符串哈希两次 (模数进制数均不同) 产生两个哈希值,比较时就可以比较两元组,更不容易冲突

  • 会有很多取模,时间上更慢
#include<bits/stdc++.h>
#include<unordered_map>
#define debug cout << "debug---  "
#define debug_ cout << "\n---debug---\n"
#define oper(a) operator<(const a& ee)const
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define all(a) a.begin(),a.end()
#define sz(a) (int)a.size()
#define endl "\n"
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 1e5 + 10, M = 2e6 + 10, mod = 1e9 + 7;
int INF = 0x3f3f3f3f; ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, B = 10, ki;

const int mod1 = 1e9 + 9;

ll p1[N], P1 = 131, p2[N], P2 = 13331;
ll h[N], h2[N];
//乘法开ll,mod取int

int get1(int l, int r) {
    return (h[r] - (h[l - 1] * p1[r - l + 1]) % mod + mod) % mod;
}
int get2(int l, int r) {
    return (h2[r] - (h2[l - 1] * p2[r - l + 1]) % mod1 + mod1) % mod1;
}

char str[N];

void solve() {
    cin >> n >> m;
    cin >> str + 1;

    p1[0] = p2[0] = 1;

    for (int i = 1; i <= n; i++) {
        p1[i] = (p1[i - 1] * P1) % mod;
        p2[i] = (p2[i - 1] * P2) % mod1;

        h[i] = ((h[i - 1] * P1) % mod + str[i] - '0' + 1) % mod;
        h2[i] = ((h2[i - 1] * P2) % mod1 + str[i] - '0' + 1) % mod1;
    }

    while (m--)
    {
        int l1, r1, l2, r2;
        cin >> l1 >> r1 >> l2 >> r2;
        if (get1(l1, r1) == get1(l2, r2) && get2(l1, r1) == get2(l2, r2))cout << "Yes\n";
        else cout << "No\n";
    }
}

signed main() {
    cinios;
    int T = 1;
    for (int t = 1; t <= T; t++) {
        solve();
    }
    return 0;
}
/*
*/
//板子
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值