C/C++ Hash表

Hash表由hash函数(映射函数)与邻接表共同实现,常用于将庞大的信息映射到一个更小的值域内进行维护。(如统计序列中不同数字出现的次数)
当hash函数设计较好时,原始信息会被较均匀地分配到各个表头之后,从而使每次查找的时间复杂度近似为O(1)。
最常用的hash函数:hash(x) = (x mod P) + 1(P是一个较大的质数),这样能使x从原来的值域变为1~P。

例题:POJ3349 Snowflake Snow Snowflakes(有最多105片雪花,每片雪花由六个角的数值(0~107-1)组成,当两个雪花从任一个角开始顺时针/逆时针往后能得到相同的六元组时,这两个雪花相同。现给定所有雪花的信息(某一角开始顺/逆时针得到的六元组),判断所有雪花中有无相同的雪花)。
解题思路:
设ai表示第i个角的长度,设计hash函数为(还有更好的hash函数,可自行设计)
h a s h ( x ) = ( Σ i = 1 6 a i 2 ) m o d ( 1 0 5 + 1 ) hash(x) = (\overset {6}{\underset {i=1}{\Sigma}} a_i^2)mod (10^5+1) hash(x)=(i=1Σ6ai2)mod(105+1)对于两片相同的雪花,他们的hash函数值必然相等。因此本题借助Hash表完成对两片雪花是否相同的判断,期望时间复杂度为O(n)。

题解代码如下

// POJ3349
# include <cstdio> 
# include <algorithm>
using namespace std;


const int MOD = 1e5+1;
const int MAXN = 1e5;

int head[MOD], tot;
struct { int a[6], next;} ha[MAXN+1]; 

bool same(int a[], int b[]);  // 判断两片雪花是否相同

int main() {
	int n, b[6], t, p, pre_p; scanf("%d", &n); tot = 0; 
	while (n --) {
		t = 0;
		for (int i = 0; i < 6; i ++) {
			scanf("%d", &b[i]); t = (t + (long long)b[i]*b[i]) % MOD;
		}
		pre_p = 0, p = head[t];
		while(p) {  // hash值相同,进行枚举判断
			if (same(ha[p].a, b)) { 
				printf("Twin snowflakes found.\n"); return 0;
			}
			pre_p = p; p = ha[p].next;
		}
		if (!pre_p) head[t] = ++tot; else ha[pre_p].next = ++tot;
		for (int i = 0; i < 6; i ++) ha[tot].a[i] = b[i];
	}
	printf("No two snowflakes are alike.\n");
	
	return 0;
}


bool same(int a[], int b[]) {  // 算法示例
	int pa, pb, pb2, p0 = -1;
	for (int i = 0; i < 6; i ++) {
		if (a[i] != a[0]) continue; pa = i, pb = 0;
		if (!(p0+1)) {
			while (pb < 6 && a[0] != b[pb]) pb += 1;
			if (pb >= 6) return false; p0 = pb;
		}
		pa = (pa+1)%6, pb = p0; pb2 = pb; bool f1 = true, f2 = true;
		while (pa != i && (f1 || f2)) {
			pb = (pb+1)%6; pb2 = (pb2+5)%6;
			if (a[pa] != b[pb]) f1 = false; if(a[pa] != b[pb2]) f2 = false; 
			pa = (pa+1)%6;
		}
		if (f1 || f2) return true;
	}
	return false;
}
好的,我可以为您提供一个基于SimHash算法C++程序相似性检测系统的代码实现。SimHash算法是一种快速的文本相似性度量算法,它可以将文本示成一个固定长度的二进制向量,并通过计算两个文本的哈希值的汉明距离来衡量它们的相似度。以下是代码实现: ```c++ #include <iostream> #include <string> #include <vector> #include <bitset> #include <algorithm> using namespace std; const int HASH_BITS = 64; // 定义哈希值的位数 const int K_GRAMS = 3; // 定义k-gram的长度 // 将一个字符串分成k-gram,并返回每个k-gram的哈希值 vector<uint64_t> getKGramHash(const string &s) { vector<uint64_t> hashes; for (int i = 0; i <= s.length() - K_GRAMS; i++) { uint64_t hash = 0; for (int j = 0; j < K_GRAMS; j++) { hash = (hash << 8) | s[i + j]; } hashes.push_back(hash); } return hashes; } // 计算SimHash值 bitset<HASH_BITS> getSimHash(const vector<uint64_t> &hashes) { vector<int> bits(HASH_BITS, 0); for (uint64_t hash : hashes) { for (int i = 0; i < HASH_BITS; i++) { if (hash & (1ull << i)) { bits[i]++; } else { bits[i]--; } } } bitset<HASH_BITS> simHash; for (int i = 0; i < HASH_BITS; i++) { simHash[i] = (bits[i] > 0); } return simHash; } // 计算两个SimHash值的汉明距离 int hammingDistance(const bitset<HASH_BITS> &a, const bitset<HASH_BITS> &b) { return (a ^ b).count(); } // 计算两个字符串的相似度 double similarity(const string &a, const string &b) { vector<uint64_t> aHashes = getKGramHash(a); vector<uint64_t> bHashes = getKGramHash(b); bitset<HASH_BITS> aSimHash = getSimHash(aHashes); bitset<HASH_BITS> bSimHash = getSimHash(bHashes); int distance = hammingDistance(aSimHash, bSimHash); return 100.0 - (double) distance * 100.0 / (double) HASH_BITS; } int main() { string a = "hello world"; string b = "hello world!"; string c = "goodbye world"; double similarityAB = similarity(a, b); double similarityAC = similarity(a, c); cout << "The similarity between a and b is: " << similarityAB << "%" << endl; cout << "The similarity between a and c is: " << similarityAC << "%" << endl; return 0; } ``` 这段代码实现了一个简单的C++程序相似性检测系统。它首先将输入的两个字符串分成k-gram,然后计算它们的SimHash值,并求出其汉明距离,最后用汉明距离计算相似度。您可以根据需要修改K_GRAMS和HASH_BITS的值来调整k-gram的长度和哈希值的位数,以达到更好的检测效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值