hash

一维的hash,二维hash, 康拓展开

一般的hash函数的定义

\(C = c_1c_2c_3\dotsc_m\), C代表的是一个长度为m的字符串。
hash函数的目的是用一个数字唯一的表示一个字符串。

下面就要进行递推的计算长度为m的子串的hash值了。

代码

运用了unsigned long long 自动溢出的特性,就不需要进行取模了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const ull base = 1e9+7;
bool solve(string a, string b){
int len_a = a.length();
int len_b = b.length();
if(len_a>len_b) return false;
ull t = 1;
for(int i=0; i<len_a; i++){
t*=base;
}
ull ha, hb;
ha = hb = 0;
for(int i=0; i<len_a; i++){
ha = ha*base+a[i];
hb = hb*base+b[i];
}
for(int i=0; i+len_a<=len_b; i++){
if(ha == hb) return true;
if(i+len_a<len_b){
hb = hb*base+b[i+len_a]-t*b[i];
}
}
return false;
}
int main()
{
string a, b;
while(cin>>a>>b){
if(solve(a, b)){
printf("YES\n");
}
else{
printf("NO\n");
}
}
return 0;
}

二维hash

康拓展开&八数码问题

首先需要知道康拓展开是什么?
康拓展开的本质也是hash.不同之处在它hash的初始变量是一个有排列顺序的组合。具体的原理见博文。
康拓展开

其中\(a_n\)表示它比后面的的值大的个数。

题目

hdu1430 魔板

题意

有三种变换,问怎么样从初态经过三种变换变成末态。

题解

这个题目有个小技巧就是打表。
先把所有的初始状态装化为标准状态(1, 2, 3, 4, 5, 6, 7, 8).这就相当于原来这个人交张三,现在叫李四, 人还是这个人。下面用一个例子来说明。

这样就缩小了搜索的范围,一共有8!种状态。
然后用康拓展开来进行hash搜索就行了,把每一种状态编码成一个唯一的数字,从而进行搜索。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10;
int fact[8] = {1, 1, 2, 6, 24, 120, 720, 5040};
char op[maxn];
char ed[maxn];
map<int, int> mp;
int terminal[maxn];
int change[3][8] = {{7, 6, 5, 4, 3, 2, 1, 0},
{3, 0, 1, 2, 5, 6, 7, 4},
{0, 6, 1, 3, 4, 2, 5, 7}};
string ans[40320+10];
bool vis[40320+10];
struct Node{
int num[maxn];
};
int get_hash(int* num){
int h_value = 0;
int cnt = 0;
for(int i=0; i<8; i++){
cnt = 0;
for(int j=i+1; j<8; j++){
if(num[j]<num[i]) cnt++;
}
h_value += cnt*fact[7-i];
}
return h_value;
}
void bfs(){
Node s;
for(int i=1; i<=8; i++){
s.num[i-1] = i;
}
int init_value = get_hash(s.num);
vis[init_value] = true;
queue<Node> q;
q.push(s);
while(!q.empty()){
Node temp = q.front();
q.pop();
for(int i=0; i<3; i++){
Node cur;
for(int j=0; j<8; j++){
cur.num[j] = temp.num[change[i][j]];
}
int pre_value = get_hash(temp.num);
int h_value = get_hash(cur.num);
if(!vis[h_value]){
q.push(cur);
vis[h_value] = true;
ans[h_value] = ans[pre_value]+char('A'+i);
}
}
}
}
int main()
{
bfs();
while(~scanf("%s%s", op, ed)){
mp.clear();
for(int i=0; i<8; i++){
mp.insert(make_pair(op[i]-'0', i+1));
}
for(int i=0; i<8; i++){
terminal[i] = mp[ed[i]-'0'];
}
// for(int i=0; i<8; i++){
// printf("%d ", terminal[i]);
// }
int h_value = get_hash(terminal);
cout<<ans[h_value]<<endl;
}
return 0;
}

未解决的问题

文章目录
  1. 1. 一般的hash函数的定义
    1. 1.1. 代码
  2. 2. 二维hash
  3. 3. 康拓展开&八数码问题
    1. 3.1. 题目
    2. 3.2. 题意
    3. 3.3. 题解
    4. 3.4. AC代码
  4. 4. 未解决的问题
{{ live2d() }}