故意散列碰撞

时间:2009-11-05 16:14:30

标签: math hash

我正在尝试编写一些可以进行“模糊散列”的代码。那就是:我想要几个输入散列到相同的输出,这样我就可以快速轻松地进行搜索等。如果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

5 个答案:

答案 0 :(得分:2)

让我们以SOUNDEX作为插图了解您可能正在寻找的内容......

  • 它确实散列不同但具有相同值的相似键
  • 它将允许断言实体A(比如“麦当劳”)可能与实体C相同(“MacDonnel”)

SOUNDEX的一个特点是它在特定域(名称,特定姓氏)中运行良好,并且它利用与词语发音相关联的规则 [使用英语,并扩展了许多相同来源的语言]。

如果存在(或可以发现)一组[相对简单的]规则来表达“相同性”,那么您的哈希(或几乎是一种索引形式?)算法才会成功所考虑的项目/记录。例如,如果底层数据库属于汽车,并且“相同性”的标准是大小和一般性能的标准,则散列算法可能应基于记录中的属性,例如价格(转换为范围),数量气缸,门数,估计的汽油里程(也转换为范围)。

简而言之,我希望上面说明需要根据我们希望与哈希值标识(或接近度...)相关联的语义来定制算法...因此看起来越来越像索引......),以及这些语义在项目的可用数据中表示。

项目可能在很多方面都很相似。这是一个定义这些维度的问题,这个维度上的“on”属性如何用作散列函数的关键。

在CMPH和gperf上 ...
这些是完美的,可选的mimimal哈希函数的实现。这种功能可以让您 阻止冲突。这不是我需要的(我认为)

答案 1 :(得分:1)

您可以查看MinHash,这是一种可能的方法,用于项目由集合成员资格定义的情况。

我知道你想设计自己的哈希函数,但也许这就是你要找的东西。

答案 2 :(得分:0)

哈希必须如何无冲突(就误报而言)?

怎么样:

  1. 对数字进行排序,然后在该序列上运行标准哈希值?
  2. 或者,将每个行/列视为一个集合,并使用添加来散列每个行/列的内容。然后对这些结果进行排序并在排序的总和上运行标准哈希值?
  3. 或者,1和2的乘积。
  4. 例如,这里是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可能是你最好的选择。