码迷,mamicode.com
首页 > 其他好文 > 详细

0x14 Hash

时间:2019-07-02 09:36:32      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:print   show   nbsp   char   long   字符串hash   stdin   ash   回文串   

Hash表

【例题】POJ3349 Snowflake Snow Snowflakes

建立一个哈希表,将N片雪花依次插入。

技术图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 const int INF=0x3f3f3f3f;
 8 const int maxn=100000+10;
 9 const int P=99991;
10 int n;
11 
12 int hash(int *a) {
13     int sum=0, mul=1;
14     for (int i=0; i<6; ++i) {
15         sum=(sum+a[i])%P;
16         mul=(long long)mul*a[i]%P;
17     }
18     return (sum+mul)%P;
19 }
20 
21 int tot=0, snow[maxn][6], next[maxn], head[maxn];
22 bool judge(int *a, int *b) {
23     for (int i=0; i<6; ++i) {
24         for (int j=0; j<6; ++j) {
25             bool flag=1;
26             //顺时针 
27             for (int k=0; k<6; ++k) {
28                 if (a[(i+k)%6] != b[(j+k)%6]) flag=0;
29                 //printf("%d %d %d\n", a[(i+k)%6], b[(j+k)%6], flag);
30             }
31             //printf("\n");
32             if (flag) return 1;
33             //逆时针
34             flag=1;
35             for (int k=0; k<6; ++k) {
36                 if (a[(i+k)%6] != b[(j-k+6)%6]) flag=0;
37                 //printf("%d %d %d\n", a[(i+k)%6], b[(j-k+6)%6], flag);
38             }
39             //printf("\n");
40             if (flag) return 1; 
41         }
42     }
43     return 0;
44 }
45 
46 bool insert(int *a) {
47     int val=hash(a);
48     for (int i=head[val]; i; i=next[i]) {
49         if (judge(snow[i], a)) return 1;
50     }
51     //若没有找到相同的雪花,则进行插入 
52     ++tot;
53     memcpy(snow[tot], a, 6*sizeof(int));
54     next[tot]=head[val];
55     head[val]=tot;
56     return 0;
57 }
58 
59 int main() {
60     //freopen("a.out", "w", stdout);
61     scanf("%d", &n);
62     for (int i=1; i<=n; ++i) {
63         int a[10];
64         for (int j=0; j<6; ++j)
65             scanf("%d", &a[j]);
66         if (insert(a)) {
67             printf("Twin snowflakes found.\n");
68             return 0;
69         }
70     } 
71     printf("No two snowflakes are alike.\n");
72     return 0;
73 }  
View Code

字符串Hash

取一固定值P(一般取131或13331),将字符串看作P进制数,并分配一个大于0的数值,代表每种字符。取一固定值M,求出该P进制数对M的余数,作为该字符的Hash值,通常取M=264,即用unsigned long long类型存储,溢出时自动取模。

【例题】CH1401 兔子与兔子

技术图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 const int INF=0x3f3f3f3f;
 8 const int maxn=1000000+10;
 9 char s[maxn];
10 unsigned long long f[maxn], p[maxn];
11 
12 int main() {
13     //freopen("a.txt", "r", stdin);
14     //freopen("a.out", "w", stdout);
15     scanf("%s", s+1);
16     int T;
17     scanf("%d", &T);
18     int n=strlen(s+1);
19     p[0]=1;
20     for (int i=1; i<=n; ++i) {
21         f[i]=f[i-1]*131+(s[i]-a+1);    //Hash(s[1~i])
22         p[i]=p[i-1]*131;    //131^i
23     }
24     while (T--) {
25         int l1, r1, l2, r2;
26         scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
27         unsigned long long hash1=f[r1]-f[l1-1]*p[r1-l1+1];
28         unsigned long long hash2=f[r2]-f[l2-1]*p[r2-l2+1];
29         if (hash1==hash2) puts("Yes");
30         else puts("No");
31     }
32     return 0;
33 }  
View Code

【例题】POJ3974 Palindrome

枚举回文中心,提前预处理出正着和反着的Hash值

技术图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 const int INF=0x3f3f3f3f;
 8 const int maxn=1000000+10;
 9 char s[maxn];
10 unsigned long long f1[maxn], f2[maxn], p[maxn];
11 
12 int main() {
13     //freopen("a.txt", "r", stdin);
14     //freopen("a.out", "w", stdout);
15     int kase=0;
16     p[0]=1;
17     for (int i=1; i<=maxn; ++i)
18         p[i]=p[i-1]*131;    //131^i 
19     while (~scanf("%s", s+1)) {
20         int n=strlen(s+1);
21         if (n==3&&s[1]==E&&s[2]==N&&s[3]==D)
22             break;
23         printf("Case %d: ", ++kase);
24         for (int i=1; i<=n; ++i)    //正着算一遍 
25             f1[i]=f1[i-1]*131+(s[i]-a+1);
26         for (int i=n; i>=1; --i)    //反着算一遍 
27             f2[i]=f2[i+1]*131+(s[i]-a+1);
28         int ans=-INF;
29         for (int i=1; i<=n; ++i) {    //枚举回文中心 
30             int l=1, r=min(i-1, n-i);
31             while (l<r) {    //奇回文串 
32                 int mid=(l+r+1)>>1;
33                 if (f1[i-1]-f1[i-1-mid]*p[mid]==f2[i+1]-f2[i+1+mid]*p[mid]) l=mid;
34                 else r=mid-1;
35             }
36             ans=max(ans, l*2+1);
37             l=1, r=min(i, n-i);
38             while (l<r) {    //偶回文串 
39                 int mid=(l+r+1)>>1;
40                 if (f1[i]-f1[i-mid]*p[mid]==f2[i+1]-f2[i+1+mid]*p[mid]) l=mid;
41                 else r=mid-1;
42             }
43             ans=max(ans, l*2);
44         }
45         printf("%d\n", ans);
46     }
47     return 0;
48 }  
View Code

 

0x14 Hash

标签:print   show   nbsp   char   long   字符串hash   stdin   ash   回文串   

原文地址:https://www.cnblogs.com/kkkstra/p/11118414.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!