用于识别具有哈希且无误报的字符串匹配项的算法
algorithm to identify string matches with hashing and no false positives
我需要查找给定的字符串是否与列表中的字符串匹配,而列表中没有字符串;基本上我需要对字符串进行哈希处理,并且仅与哈希列表匹配。问题是确保没有误报,以便只找到完全匹配项,而找不到任何其他字符集。对于实际的字符串列表,这当然很容易,即使是简单的二进制搜索也可以,但我想要一种在没有实际字符存在(即预先计算)的情况下工作的算法。布隆过滤器无法保证某些任意字符集可能不匹配。
更新:这类似于仅存储密码哈希,然后对输入的密码进行哈希处理,然后将其与哈希列表进行比较,以查看密码是否是其中之一(诚然,这不是通常使用的密码)。此要求的原因是不必提供实际文本,只需提供哈希值。
更新2:没有完美的哈希函数,有没有另一种方法可以做到这一点?我有数十万个条目,很难找到一个完美的哈希值。也许像布隆过滤器这样的东西,但有更好的保证?
一个好的加密哈希函数(具有足够的位)将使错误匹配的概率非常小;足够小,以至于暴力攻击基本上是不可能的。大多数安全系统认为这种机制是充分的。
如果你想要一个绝对的保证,没有误报的可能性,那么你实际上需要包含足够的数据来验证输入;它不能比目标字符串短(但它不必更大)。实际上,您需要加密目标字符串。由于加密密钥和加密字符串都是可见的,为了避免有人简单地解密加密字符串,您需要使用非对称密码。这些计算成本很高,但对于您的环境来说可能不是问题。
任何完美的哈希都可以。 使用字符串比较跟进它,以验证它不是误报。
这是一个"近乎完美"的哈希算法:
MPQ 哈希
它用于星际争霸保存文件。该算法非常有效,并且具有非常低的碰撞可能性(平均约为1:18889465931478580854784)。
以下是该算法的工作原理。
1.计算三个哈希(偏移哈希和两个检查哈希)并将它们存储在变量中。
2.移至偏移哈希的条目
3.Is 条目未使用?如果是这样,请停止搜索并返回"找不到文件"。
两个检查哈希 4.Do 与我们正在寻找的文件的检查哈希匹配?如果是这样,请停止搜索并返回当前条目。
5.移动到列表中的下一个条目,如果我们在最后一个条目上,则绕到开头。
6.Is 我们刚刚移动到与偏移哈希相同的条目(我们是否查看了整个哈希表?如果是这样,请停止搜索并返回"找不到文件"。
7.返回步骤 3。
这是哈希和哈希表函数:
unsigned long HashString(char *lpszFileName, unsigned long dwHashType)
{
//lpszFileName is the string to be hashed.
//dwHashType will change the hash value according to hash mode.
//You can see how it's used in the beginning of GetHashTablePos().
unsigned char *key = (unsigned char *)lpszFileName;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch;
while(*key != 0)
{
ch = toupper(*key++); //Convert every character to upper case.
//dwHashType will change the hash value in different hashing modes.
//(Whether to calculate the position or to verify.)
seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}
int GetHashTablePos(char *lpszString, MPQHASHTABLE *lpTable, int nTableSize)
{
const int HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
//nHash controls where the hash value of the string should be stored in the hash table.
//nHashA and nHashB are used for verifying the match
int nHash = HashString(lpszString, HASH_OFFSET),
nHashA = HashString(lpszString, HASH_A),
nHashB = HashString(lpszString, HASH_B),
nHashStart = nHash % nTableSize, nHashPos = nHashStart;
while (lpTable[nHashPos].bExists)
{
if (lpTable[nHashPos].nHashA == nHashA && lpTable[nHashPos].nHashB == nHashB)
return nHashPos; //If found, return the entry index
else
nHashPos = (nHashPos + 1) % nTableSize; //Not found, move to next position
if (nHashPos == nHashStart)
break; //Reach the beginning of table, stop searching.
}
return -1; //Error value
}
您可以考虑将布隆过滤器放在一起。 这基本上是一组哈希算法和哈希表,当它们作为一个组时,可以给出非常高的正确匹配概率。 它不是 100%,但您可以随心所欲地接近它。
- 从 argv[1] 转换为字符 * 字符串后有什么问题?
- 将 NULL 与 C 的字符* 字符串一起使用
- 无法在声明时使用初始值设定项列表初始化常量字符*/字符串数组的向量
- 无法将常量字符字符串传递给模板类
- 如何组合一个宽字符字符串,中间插入一些空字符
- 如何将二维数组类型字符(字符串)作为函数参数传递?
- 从给定索引返回子字符字符串的函数
- 字符 [](c 字符串)的初始化标准
- 如何将字符字符串用作数学运算符
- 将 Unicode 字符/字符串写入文件
- C++,字符* 字符串修改
- 如何有效地用不同的整数元素替换字符字符串的元素
- C++:如果我们在字符串中添加一些整数,为什么它会从开头删除该数量的字符?(字符串 + 整数)
- strcpy正在复制sth字符i字符串.如何解决此错误
- 在C++中将双精度转换为字符*/字符串
- C 中的宽字符字符串
- 如何提取C 中的字符/字符串之间的字符串
- 无法将字符/字符串转换为int
- 带有指针的反转字符字符串
- 反转字符串中的 n 个字符(字符串中没有空格),而不使用 c++ 中的内置函数