我想从一个文本(在我的例子中是html)中制作一种哈希键,它与其他类似文本的哈希匹配/比较
ex匹配文本:
到目前为止,我一直在考虑删除数字和标签,但是仍然会留下随机字样。
那有什么剂量吗?
我有对服务器的root权限,所以我可以添加任何必要的UDF,如果需要,我可以用c或其他语言进行处理。
理想的是像generateSimilarHash(text)
这样的函数和另一个函数compareSimilarHashes(hash1,hash2)
,它将返回匹配文本的过程。
像compare(text1,text2)这样的函数不能像我的情况一样工作,因为我有很多页面需要比较(目前大约20 mil)
欢迎任何建议!
答案 0 :(得分:2)
我从来没有做过这样的事情,只是根据一般的散列知识抛出一些东西。
首先,一般来说,我怀疑你可以表示你想要比较的整个字符串,因为一个值从中进行了散列,然后有意义地使用它来找到近似匹配。散列函数通常被设计为从输入值的微小变化产生巨大的伪随机输出值差异 - 因此天真地使用它们不是这个问题的良好匹配,但是...
可能有用的是使用一些约定将长文本分成子部分,例如寻找至少N个字符的终止标点符号(句号,感叹号,问号),然后你可以散列那些单独的子字符串并使用计数匹配哈希以近似匹配文本的数量。
您必须计算出合适的粒度级别才能将文本划分为合理数量的不同哈希值 - 平衡哈希值的大小和哈希比较的速度与匹配的准确性。您可能还想进行一些先前的转换,例如将字符转换为单个大小写或用一个空格替换一个或多个空白字符的每个区域,或许用空格替换标点符号:这种微不足道的差异不会导致哈希值不匹配 - 调整味道。
在你的例子中:
“2012/10/01这是我的网页#1”+ 100k_of_same_text + random_words_1 + ..
假设您在全站点中断,或者没有完全停止,我们会按照排序的单词顺序找到本地最小值,以便最多5-20个单词出现在一个部分中......您最终可能会遇到以下子句:
然后在上面的每一个上使用普通的字符串散列函数。要将此与其他类似散列的文本进行比较,您需要查找匹配的哈希值的数量(如果您没有为匹配的文本子部分的顺序或连续性赋予一定的重要性,那么迭代预先排序的列表是非常有效的两组哈希,或者使用哈希值预填充哈希表然后依次查找每个哈希表。
答案 1 :(得分:1)
我想我会回答这个问题,因为我正在研究类似的问题。这种具有很高碰撞机会的类似对象的哈希思想的名称是“局部敏感哈希”。有很多关于这个主题的文献,但这里有一个简单的例子:
想象一下,我们有一个固定长度的二进制向量{1,0}。我们可以使用内置的stl和boost算法选择一个随机的索引子集来计算哈希:
library(data.table)
tmp <- melt(setDT(df2), 1)[, level := sub("std", "", variable, fixed = TRUE)]
setDT(df1)[tmp, Amount := value, on = c(drugs = "standards", "level")]
df1
# drugs level Amount
# 1: Drug1 1 100
# 2: Drug1 2 200
# 3: Drug1 3 300
# 4: Drug2 1 100
# 5: Drug2 2 200
# 6: Drug2 3 300
然后,如果迭代对象仅在这些索引处相等,则它们具有相同的散列和相等的值:
即在我的电脑上
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <algorithm>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/functional/hash.hpp>
template<class It, class pred>
std::size_t hash_filtered_range(It first, It last, pred f){
return boost::hash_range(boost::make_filter_iterator(f, first, last),
boost::make_filter_iterator(f, last, last));
}
template<class iter>
struct IterableHash{
IterableHash(const iter indices_begin, const iter indices_end): _inc_indices(indices_begin, indices_end){
}
template <class obj_type>
std::size_t operator()(const obj_type& type)const{
int _ix = 0;
return hash_filtered_range(std::begin(type), std::end(type), [this, &_ix](const auto& t){
return (this->_inc_indices.find(_ix++) != this->_inc_indices.end());
});
}
private:
std::unordered_set<int> _inc_indices;
};
template<class hasher>
struct ApproxEqual{
ApproxEqual(const hasher& hash):hash(hash) {}
template<class obj_type>
bool operator() (const obj_type& o1, const obj_type& o2)const{
return hash(o1) == hash(o2);
}
private:
hasher hash;
};
产生
11093822460655
11093822460655
33
即我们在使用fuzzy_res查询时恢复不同向量res的值;
答案 2 :(得分:0)
您可以尝试在随机单词上使用DJB哈希算法。然后比较哈希键。实际上,两个不同的文本总是有一个很小的机会给出相同的结果......但是如果32位的散列不够,你可以将它扩展到64位和/或保留对文本的引用来比较它们哈希是相同的。
此处有更多详情:DJB Hash