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 }
字符串Hash
取一固定值P(一般取131或13331),将字符串看作P进制数,并分配一个大于0的数值,代表每种字符。取一固定值M,求出该P进制数对M的余数,作为该字符的Hash值,通常取M=264,即用unsigned long long类型存储,溢出时自动取模。
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 }
枚举回文中心,提前预处理出正着和反着的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 }
原文地址:https://www.cnblogs.com/kkkstra/p/11118414.html
时间: 2024-10-18 23:51:11