双哈希

就是构造两个哈希函数,然后将结果记为pair存map,能够进一步减少冲突率

例题:Birthday Cake

题意

给你n个串,问有几对串可以拼成形如AA串。

思路

先对所有串跑一个哈希,然后遍历所有串,如果该串是ABA型那么就去找B的个数,自然溢出法还差一点,双哈希就过了。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define pll pair<ll,ll>
const int maxn = 4e5 + 5;
ll Mod1 = 1e9 + 9, Mod2 = 1e9 + 11;
ll ha1[maxn], ha2[maxn], p1[maxn], p2[maxn], bas = 233;
pll res[maxn];
int cc = 0;
map<pll, ll> cnt;
ll get1(int l, int r){ //子串hash1
    return (ha1[r] - ha1[l - 1] * p1[r - l + 1] % Mod1 + Mod1 ) % Mod1;
}
ll get2(int l, int r){ //子串hash2
    return (ha2[r] - ha2[l - 1] * p2[r - l + 1] % Mod2 + Mod2 ) % Mod2;
}
pll get(int l, int r){ //成pair用于存map,或者计算数量
    return {get1(l, r), get2(l, r)};
}
int main(){
    cin.tie(0);ios::sync_with_stdio(false);
    int n; cin >> n;
	//预处理bas的幂次,用于获取子串用
    p1[0] = 1;
    for(int i = 1; i < maxn; i ++) p1[i] = p1[i - 1] * bas % Mod1;
    p2[0] = 1;
	for(int i = 1; i < maxn; i ++) p2[i] = p2[i - 1] * bas % Mod2;
    
	for(int i = 1; i <= n; i ++){
        string a; cin >> a;
        int len = a.length();
        for(int j = 1; j <= len; j ++){
			//跑hash数组
            ha1[j] = ha1[j - 1] * bas % Mod1 + a[j - 1] - 'a' + 1;
            ha2[j] = ha2[j - 1] * bas % Mod2 + a[j - 1] - 'a' + 1;
            ha1[j] %= Mod1; ha2[j] %= Mod2;
        }
        cnt[{ha1[len], ha2[len]}] ++;
        for(int j = 1; j + j < len; j ++){
            if(get(1, j) == get(len - j + 1, len)) res[++ cc] = get(j + 1, len - j); // 如果是ABA型就先把B存下来,最后一起找
        }
    }
    ll ans = 0;
    for(int i = 1; i <= cc; i ++) ans += cnt[res[i]];
    for(auto it : cnt) ans += it.second * (it.second - 1) / 2; //这里是同一个串出现超过1次的情况
    cout << ans << endl;
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值