继续快速相似文件查询的研究,用到一篇文献的思想,对其进行仿真。
文献:A Fast Approximate Nearest Neighbor Search Algorithm in the Hamming Space
该文献的主要思想是:输入文件的哈希值(我用的是文件名)例如一个64位的哈希值,多次随机抽取若干位(例如4位)的值组成一个字串,按照字串值的不同将文件放入不同的哈希桶中。这样一个64位哈希值将被放入64/4=16个桶中,查询时把所有查询点也哈希成64位哈希值,按照相同的方式随机抽取,把所在桶中所有的字符串全部拿出来做候选集。同时,为了进一步提高查全率设定一个权重值(度量汉明距离),准备一个汉明字典将所有字串和其他汉明字串的值记录用以将权重值内的桶的字符串也做为候选集。
这个程序是用于产生汉明字典的工具类。
- package test;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- import org.junit.Test;
- /**
- * 产生二进制串字典的工具类
- * @author edward
- * @data 2014.8.16 8.18
- * @return 输出二进制串的所有可能组合 到文件 暂时考虑4位,8位,16位(他们可以被64位整除)
- * */
- public class GeneBinStrUtil {
- int length[]={4,8,16};
- int sum[]={16,256,65536};
- String a[]=new String[sum[0]],
- b[]=new String[sum[1]];
- // String c[]=new String[length[2]]; //TODO 数组大小的限制是?
- //二维数组A存放的是长度为4的二进制串的汉明距离字典
- //这个矩阵的每一行对应一个二进制串和其他所有相同长度的二进制串的汉明距离。
- //这个矩阵的对角线元素没有赋值为0,这是可以直接知道的。事实上计算的是一个上三角。
- String A[][]=new String[sum[0]][sum[0]];
- String B[][]=new String[sum[1]][sum[1]];
- @Test
- public void GeneTest() throws Exception{
- for(int i=0;i<length.length;i++){
- int t=0;
- // System.out.println(String.format("%05d %s", t,Integer.toBinaryString(t)));
- for(int j=0;j<sum[i];j++){
- if(i==0){
- //为了得到指定长度的字符串 做了特殊处理
- a[j]=String.format("%04d",Integer.valueOf(Integer.toBinaryString(t)));
- // System.out.println(a[j]);
- }
- else if(i==1){
- b[j]=String.format("%08d",Integer.valueOf(Integer.toBinaryString(t)));
- // System.out.println(b[j]);
- }
- else{
- // c[j]=Integer.toBinaryString(t);
- if(i==2)break; //暂时只考虑前两组
- }
- t+=1;
- // System.out.println(String.format("%05d %s", t,Integer.toBinaryString(t)));
- }
- }
- geneHamMatrix(A,a);
- for(int i=0;i<sum[0];i++)
- sort(A[i]);
- writeArray("dataset/dic_4bit.txt",A);
- geneHamMatrix(B,b);
- for(int i=0;i<sum[1];i++)
- sort(B[i]);
- writeArray("dataset/dic_8bit.txt",B);
- /**/
- }
- public int hamDis(String str1, String str2) {
- int tot = 0;
- if(str1.length()!=str2.length()) return -1;
- for(int i=0;i<str1.length();i++){
- if(str1.charAt(i)!=str2.charAt(i))tot++;
- }
- // System.out.println(tot);
- return tot;
- }
- public String[] sort(String str[]){
- String temp=null;
- for(int i=0;i<str.length-1;i++){
- for(int j=i+1;j<str.length;j++){
- if(str[i].compareTo(str[j])>0){
- temp=str[i];
- str[i]=str[j];
- str[j]=temp;
- }
- }
- }
- return str;
- }
- /**
- *Function: calculate the hamming distance matrix,
- *based on the result got with calling of "HanDis".
- *@param String target[][] --the container to store the hamming distances
- *@param String sc[] --the binary string that needed to be handled.
- */
- public void geneHamMatrix(String target[][], String sc[]){
- int dis=0;
- for(int i=0;i<sc.length-1;i++){
- target[i][i]=sc[i];
- for(int j=i+1;j<sc.length;j++){
- dis=hamDis(sc[i],sc[j]);
- target[i][j]=dis+"_"+sc[j];
- target[j][i]=dis+"_"+sc[i];
- }
- }
- target[sc.length-1][sc.length-1]=sc[sc.length-1]; //补充填充
- }
- /**
- *Function: write the hamming distance matrix into a file.
- *@param String path-- file path.
- *@param String array[][] -- the hamming distance matrix.
- */
- public void writeArray(String path, String array[][]) throws Exception{
- File f = new File(path);
- if(f.exists())f.delete();
- //用FileOutputSteam包装文件,并设置文件可追加
- OutputStream out = new FileOutputStream(f,true);
- for(int i=0;i<array[0].length;i++)
- for(int j=0;j<array[0].length;j++){
- out.write(array[i][j].getBytes()); //向文件中写入数据
- out.write('\r'); // \r\n表示换行
- out.write('\n');
- }
- out.close(); //关闭输出流
- System.out.println("写入成功!");
- }
- }