算法竞赛中的哈希是往往是种种概率/玄学但是又贼鸡儿快方便的神奇算法
本质是通过对目标数据建立唯一映射进行缩小数据规模的权值判断, 常常可以乱搞一些题目
对循环数组的hash
解题思路: 对每个六元组求最小表示, 然后用乘积与和对应的双hash映射入一个链表 再判断即可
字符串哈希
https://www.acwing.com/problem/content/140/ 子串hash模板题
http://www.51nod.com/Challenge/Problem.html#!#problemId=1089 最长回文子串hash O(n) 算法
再也不用记马拉车了233
解法: 字符串hash常使用进制转化法, 具有类前缀和的性质
MODhash
const ull MOD = 386910137;
ull pre[MAXN];
ull fac[MAXN] = {1};
ull gethash(ull *pre, int a, int b)
{
return (pre[b] - pre[a - 1] * fac[b - a + 1] % MOD + MOD) % MOD;
}
fr(i, 1, 1e6 + 10) //预处理阶乘
{
fac[i] = (fac[i - 1] * P) % MOD;
}
pre[flag] = (pre[flag - 1] * P % MOD + x[j]) % MOD; //预处理hash
自然溢出
ull pre[MAXN], fac[MAXN] = {1}; //自然溢出法
cin >> s + 1
for(int i = 1; i <= len; ++i) //建立hash table
{
fac[i] = fac[i - 1] * P;
pre[i] = pre[i - 1] * P + s[i];
}
ull getprehash(int a, int b) //查询任意字串的hash值
{
return pre[b] - pre[a - 1] * fac[b - a + 1];
}
最长回文子串的hash求法
/*
Zeolim - An AC a day keeps the bug away
*/
//pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 10;
const ll MOD = 1e9 + 7;
const ull P = 131;
ull pre[MAXN], fac[MAXN] = {1}, pio[MAXN];
char s[MAXN];
ull getprehash(int a, int b)
{
return pre[b] - pre[a - 1] * fac[b - a + 1];
}
ull getpiohash(int a, int b)
{
return pio[a] - pio[b + 1] * fac[b - a + 1];
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
int flag = 1;
while(cin >> s + 1)
{
if(s[1] == 'E' && s[2] == 'N' && s[3] == 'D')
break;
int len = strlen(s + 1);
pio[len + 1] = 1;
int ans = 1, pis = 0, apis = 0;
for(int i = 1; i <= len; ++i)
{
fac[i] = fac[i - 1] * P;
pre[i] = pre[i - 1] * P + s[i];
}
for(int i = len; i >= 1; --i)
{
pio[i] = pio[i + 1] * P + s[i];
}
for(int i = 1; i <= len; ++i)
{
int rpis = pis + 1;
while(i - rpis >= 1 && i + rpis <= len && getprehash(i - rpis, i) == getpiohash(i, i + rpis))
{
ans = max(ans, rpis * 2 + 1), pis = rpis, ++rpis;
}
rpis = apis;
while(i + 1 - rpis >= 1 && i + rpis <= len && getprehash(i - rpis + 1, i + 1) == getpiohash(i, i + rpis))
{
ans = max(ans, rpis * 2), apis = rpis, ++rpis;
}
}
cout << ans << '
';
}
return 0;
}