[hash] 哈希的简单入门

算法竞赛中的哈希是往往是种种概率/玄学但是又贼鸡儿快方便的神奇算法

本质是通过对目标数据建立唯一映射进行缩小数据规模的权值判断, 常常可以乱搞一些题目


对循环数组的hash

https://www.acwing.com/problem/content/139/

 解题思路: 对每个六元组求最小表示, 然后用乘积与和对应的双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 << '\n';
    }

    return 0;
}

 

 

posted @ 2019-05-05 10:49  张浦  阅读(136)  评论(0编辑  收藏  举报