我正在尝试编写一些可以进行“模糊散列”的代码。那就是:我想要几个输入散列到相同的输出,这样我就可以快速轻松地进行搜索等。如果A哈希为1且C哈希为1,那么我发现A等于C将是微不足道的。
设计这样的哈希函数似乎很难,所以我想知道是否有人有CMPH或GPERF的经验,并且可以指导我创建一个导致这个哈希函数的函数。
提前致谢! 斯蒂芬
@Ben
在这种情况下,布尔矩阵,但我可以很容易地将它们打包成64位整数。输入中的旋转,翻译等是无关紧要的,需要将其淘汰。因此:
000
111
000
相当于
111
000
000
和
001
001
001
(简化)
@Kinopiko
到目前为止,我最好的选择是确定某种“规范”表示和设计代码,这些代码在转换到达这样的表示时终止(比如......将所有位打包在底部)。然而这很慢,我正在寻找更好的方法。我的数据集很大。
@Jason
这两个不会哈希到相同的值。
000
010
000
000
011
000
答案 0 :(得分:2)
让我们以SOUNDEX作为插图了解您可能正在寻找的内容......
SOUNDEX的一个特点是它在特定域(名称,特定姓氏)中运行良好,并且它利用与词语发音相关联的规则 [使用英语,并扩展了许多相同来源的语言]。
如果存在(或可以发现)一组[相对简单的]规则来表达“相同性”,那么您的哈希(或几乎是一种索引形式?)算法才会成功所考虑的项目/记录。例如,如果底层数据库属于汽车,并且“相同性”的标准是大小和一般性能的标准,则散列算法可能应基于记录中的属性,例如价格(转换为范围),数量气缸,门数,估计的汽油里程(也转换为范围)。
简而言之,我希望上面说明需要根据我们希望与哈希值标识(或接近度...)相关联的语义来定制算法...因此看起来越来越像索引......),以及这些语义在项目的可用数据中表示。
项目可能在很多方面都很相似。这是一个定义这些维度的问题,这个维度上的“on”属性如何用作散列函数的关键。
在CMPH和gperf上 ...
这些是完美的,可选的mimimal哈希函数的实现。这种功能可以让您 阻止冲突。这不是我需要的(我认为)
答案 1 :(得分:1)
您可以查看MinHash,这是一种可能的方法,用于项目由集合成员资格定义的情况。
我知道你想设计自己的哈希函数,但也许这就是你要找的东西。
答案 2 :(得分:0)
哈希必须如何无冲突(就误报而言)?
怎么样:
例如,这里是Java(快速和肮脏,但你明白了):
import java.util。*;
/**
*
* @author Mark Bolusmjak
*/
public class MatrixTest {
LinkedList<LinkedList<Integer>> randomMatrix(int size){
LinkedList<LinkedList<Integer>> rows = new LinkedList<LinkedList<Integer>>();
for (int i=0; i<size; i++){
LinkedList<Integer> newRow = new LinkedList<Integer>();
for (int j=0; j<size; j++){
newRow.add((int)(5*Math.random()));
}
rows.add(newRow);
}
return rows;
}
LinkedList<LinkedList<Integer>> trans(LinkedList<LinkedList<Integer>> m){
if (Math.random()<0.5){ //column translation
for (LinkedList<Integer> integers : m) {
integers.addFirst(integers.removeLast());
}
} else { //row translation
m.addFirst(m.removeLast());
}
return m;
}
LinkedList<LinkedList<Integer>> flipDiagonal(LinkedList<LinkedList<Integer>> m){
LinkedList<LinkedList<Integer>> flipped = new LinkedList<LinkedList<Integer>>();
for (int i=0; i<m.size(); i++){
flipped.add(new LinkedList<Integer>());
}
for (LinkedList<Integer> mRows : m) {
Iterator<Integer> listIterator = mRows.iterator();
for (LinkedList<Integer> flippedRows : flipped) {
flippedRows.add(listIterator.next());
}
}
return flipped;
}
public static void main(String[] args) {
MatrixTest mt = new MatrixTest();
LinkedList<LinkedList<Integer>> m = mt.randomMatrix(4);
mt.display(m);
System.out.println(mt.hash1(m));
System.out.println(mt.hash2(m));
m = mt.trans(m);
mt.display(m);
System.out.println(mt.hash1(m));
System.out.println(mt.hash2(m));
m = mt.flipDiagonal(m);
mt.display(m);
System.out.println(mt.hash1(m));
System.out.println(mt.hash2(m));
m = mt.trans(m);
mt.display(m);
System.out.println(mt.hash1(m));
System.out.println(mt.hash2(m));
m = mt.flipDiagonal(m);
mt.display(m);
System.out.println(mt.hash1(m));
System.out.println(mt.hash2(m));
}
private void display(LinkedList<LinkedList<Integer>> m){
for (LinkedList<Integer> integers : m) {
System.out.println(integers);
}
System.out.println("");
}
int hash1(LinkedList<LinkedList<Integer>> m){
ArrayList<Integer> sorted = new ArrayList<Integer>();
for (LinkedList<Integer> integers : m) {
for (Integer integer : integers) {
sorted.add(integer);
}
}
Collections.sort(sorted);
return sorted.hashCode();
}
int hash2(LinkedList<LinkedList<Integer>> m){
List<Integer> rowColumnHashes = new ArrayList<Integer>();
for (LinkedList<Integer> row : m) {
int hash = 0;
for (Integer integer : row) {
hash += integer;
}
rowColumnHashes.add(hash);
}
m = flipDiagonal(m);
for (LinkedList<Integer> row : m) {
int hash = 0;
for (Integer integer : row) {
hash += integer;
}
rowColumnHashes.add(hash);
}
Collections.sort(rowColumnHashes);
return rowColumnHashes.hashCode();
}
} // end of class
答案 3 :(得分:0)
在你的示例矩阵中,旋转和翻译等在我看来几乎涵盖了所有内容,以至于你的算法会说所有矩阵都是相等的。您能举例说明不同的矩阵集吗?
此外,看起来你正在做类似图像搜索的事情 - 用于识别相同但可能缩放,旋转(可能是任意),翻转等图像的算法。我不知道任何这个东西,但也许你可以期待那个研究领域的灵感。
另外,我似乎还记得了Vector Calc中关于特征值的一些内容,你可能会觉得它很有用。
答案 4 :(得分:0)
cmph实现的chd算法可以做k-perfect哈希,我认为它正是你想要的:
http://cmph.sourceforge.net/chd.html
然而,最好通过“大输入”来了解你的意思。如果您正在谈论成千上万的条目,那么有更直接的解决方案。如果你有数亿,那么chd可能是你最好的选择。