关于SimHash算法的实现及测试V1.0
@祁俊辉,2017年5月21日测试。
1 说明
- 本程序是简化版的SimHash算法(分词暂为手动分词,每个词的权重都设为1);
- 本程序是基于《数学之美 》第二版第16章所介绍的原理展开;
- 本篇文章将计算多个字符串的SimHash值,并将对其分析;
- 本篇文章暂不介绍SimHash算法的原理,因为网上的资源相对较杂,待我彻底理解,整理过后更新(已在笔记本中);
- 本篇文章(程序)将持续更新。
2 程序(32位)
关于程序的解释,都在程序源码中有相应的注释。若有不明白之处,请联系本人:qce.hui@qq.com。
1 /* 【算法】SimHash->32位 2 * 【说明】1.本程序手动分词,假设每个词的权重都为1 3 * 【说明】2.对每个词进行BKDRHash算法,在此基础上加减权重 4 * 【说明】3.将所有词整合后,降维 5 * 【说明】4.计算各个句子的海明距离 6 * 【时间】祁俊辉->2017.5.19 7 * */ 8 public class SimHash_32 { 9 //定义待比较的字符串 10 static String s1="SimHash/算法/的/研究"; 11 static String s2="SimHash/算法/的/探讨"; 12 static String s3="SimHash/研究/的/算法"; 13 static String s4="SimHash/是/一种/文本/相似性/算法"; 14 //定义待比较的字符串 15 static String s5="电视剧/小时代/由/郭敬明/的/同名/小说/改编/而/成/故事/以/经济/飞速/发展/的/上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照"; 16 static String s6="电视剧/大时代/由/郭敬明/的/同名/小说/改编/而/成/该剧情/以/经济/飞速/发展/的/大上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照"; 17 //定义待比较的字符串 18 static String s7="你/妈妈/喊/你/回家/吃饭/哦/回家/喽/回家/喽"; 19 static String s8="你/妈妈/叫/你/回家/吃饭/哦/回家/喽/回家/喽"; 20 /* 函数名:BKDR_Hash(String str) 21 * 功能:计算字符串str的32位hash值,并将其以int型返回 22 * */ 23 static int BKDR_Hash(String str){ 24 int seed=131; 25 int hash=0; 26 for(int i=0;i<str.length();i++){ 27 hash=hash*seed+str.charAt(i); 28 //System.out.println(hash); 29 } 30 return (hash & 0x7FFFFFFF);//32位 31 //return (hash & 0x7FFFFFFFFFFFFFFFL);//64位 32 } 33 /* 函数名:First_FC(String str) 34 * 功能:1.先创建一个存储SimHash值的32数组,并初始化为0 35 * 功能:2.将str字符串分词,并存入临时数组 36 * 功能:3.计算此字符串的SimHash值(加权、但没有降维),存储在数组中 37 * 功能:4.将数组中的SimHash值降维,并以字符串形式返回 38 * */ 39 static String First_FC(String str){ 40 //1.先创建一个存储SimHash值的32数组,并初始化为0 41 int Hash_SZ[] = new int[32]; 42 for(int i=0;i<Hash_SZ.length;i++) 43 Hash_SZ[i]=0; 44 //2.将str字符串分词,并存入临时数组 45 String[] newstr = str.split("/"); 46 //下面的for循环是为了增加前后文关联性//即12/23/34/45··· 47 /*for(int i=0;i<newstr.length-1;i++){ 48 newstr[i]=newstr[i]+newstr[i+1]; 49 }*/ 50 //相应的,若增加上面的关联性语句,下面一行的代码要改为 51 //for(int i=0;i<newstr.length-1;i++){ 52 //3.计算此字符串的SimHash值(加权、但没有降维),存储在数组中 53 for(int i=0;i<newstr.length;i++){//循环传入字符串的每个词 54 int str_hash=BKDR_Hash(newstr[i]);//先计算每一个词的Hash值(32位) 55 //System.out.println(Integer.toBinaryString(str_hash)); 56 //对每个词的Hash值(32位)求j位是1还是0,1的话加上该词的权重,0的话减去该词的权重 57 for(int j=0;j<Hash_SZ.length;j++){ 58 int flag = (str_hash>>j)&1;//不要忘记上面计算的值是十进制,并不能直接知道j位是多少 59 //System.out.println(flag); 60 if(1 == flag){ 61 Hash_SZ[j]++;//权重先设置为1//Hash_SZ中,0是最低位,依次排高 62 }else{ 63 Hash_SZ[j]--; 64 } 65 } 66 } 67 //4.将数组中的SimHash值降维,并以字符串形式返回 68 String SimHash_number="";//存储SimHash值 69 for(int i=Hash_SZ.length-1;i>=0;i--){//从高位到低位 70 System.out.print(Hash_SZ[i]+" ");//输出未降维的串 71 if(Hash_SZ[i]<=0)//小于等于0,就取0 72 SimHash_number += "0"; 73 else//大于0,就取1 74 SimHash_number += "1"; 75 } 76 System.out.println("");//换行 77 return SimHash_number; 78 } 79 /* 函数名:HMJL(String a,String b) 80 * 功能:a、b都是以String存储的二进制数,计算他们的海明距离,并将其返回 81 * */ 82 static int HMJL(String a,String b){ 83 char[] FW1 = a.toCharArray();//将a每一位都存入数组中 84 char[] FW2 = b.toCharArray();//将b每一位都存入数组中 85 int haiming=0; 86 if(FW1.length == FW2.length){//确保a和b的位数是相同的 87 for(int i=0;i<FW1.length;i++){ 88 if(FW1[i] != FW2[i])//如果该位不同,海明距离加1 89 haiming++; 90 } 91 } 92 return haiming; 93 } 94 95 public static void main(String[] args) { 96 String a1 = First_FC(s1); 97 String a2 = First_FC(s2); 98 String a3 = First_FC(s3); 99 String a4 = First_FC(s4); 100 System.out.println("【s1】的SimHash值为:"+a1); 101 System.out.println("【s2】的SimHash值为:"+a2); 102 System.out.println("【s3】的SimHash值为:"+a3); 103 System.out.println("【s4】的SimHash值为:"+a4); 104 System.out.println("【s1】和【s2】的海明距离为:"+HMJL(a1,a2)); 105 System.out.println("【s1】和【s3】的海明距离为:"+HMJL(a1,a3)); 106 System.out.println("【s1】和【s4】的海明距离为:"+HMJL(a1,a4)); 107 System.out.println("【s2】和【s3】的海明距离为:"+HMJL(a2,a3)); 108 System.out.println("【s2】和【s4】的海明距离为:"+HMJL(a2,a4)); 109 System.out.println("【s3】和【s4】的海明距离为:"+HMJL(a3,a4)); 110 111 String a5 = First_FC(s5); 112 String a6 = First_FC(s6); 113 String a7 = First_FC(s7); 114 String a8 = First_FC(s8); 115 System.out.println("【s5】的SimHash值为:"+a5); 116 System.out.println("【s6】的SimHash值为:"+a6); 117 System.out.println("【s7】的SimHash值为:"+a7); 118 System.out.println("【s8】的SimHash值为:"+a8); 119 System.out.println("【s5】和【s6】的海明距离为:"+HMJL(a5,a6)); 120 System.out.println("【s5】和【s7】的海明距离为:"+HMJL(a5,a7)); 121 System.out.println("【s5】和【s8】的海明距离为:"+HMJL(a5,a8)); 122 System.out.println("【s6】和【s7】的海明距离为:"+HMJL(a6,a7)); 123 System.out.println("【s6】和【s8】的海明距离为:"+HMJL(a6,a8)); 124 System.out.println("【s7】和【s8】的海明距离为:"+HMJL(a7,a8)); 125 } 126 }
3 测试结果
3.1 第一个测试A1
测试时使用短字符串,对每个词使用的是32位BKDRHash算法,此次测试并未考虑上下文相关性,四个字符串分别为:
- S1:SimHash/算法/的/研究
- S2:SimHash/算法/的/探讨
- S3:SimHash/研究/的/算法
- S4:SimHash/是/一种/文本/相似性/算法
未降维时四个字符串的SimHash值为:
降维后的SimHash值为:
计算各个字符串之间的海明距离:
从上可以看出,S1和S3之间的海明距离竟然为0,这是因为并未考虑上下文相关性,而S1和S3是相同的内容,但顺序不同。
另外,看似最相似的S1和S2之间的海明距离为4(因为这两个字符串只有最后两个字不一样)。
最后,S1、S2、S3都与S4之间的海明距离较大(比其他各个之间的大),这一点还蛮准确。
3.2 第二个测试A2
测试时使用短字符串,对每个词使用的是32位BKDRHash算法,此次测试考虑上下文相关性(主要是与第一个测试A1做对比),四个字符串分别为:
- S1:SimHash/算法/的/研究
- S2:SimHash/算法/的/探讨
- S3:SimHash/研究/的/算法
- S4:SimHash/是/一种/文本/相似性/算法
注:“考虑上下文相关性”,即比如S1字符串,将其分解为:“SimHash算法”、“算法的”、“的研究”。
未降维时四个字符串的SimHash值为:
降维后的SimHash值为:
计算各个字符串之间的海明距离:
从上可以看出,在这次测试的结果中,S1和S2之间的的海明距离最小(为6),也就是这两个字符串最为相似,这与预料中的是一样的。
另外,因为考虑到上下文相关性,S1和S3之间的海明距离也不再是0,说明这两个字符串之间还是有差别的。
最后,S1、S2、S3都与S4之间的海明距离较大(比其他各个之间的大),这一点相对于第一个测试A1更为明显。
3.3 第三个测试A3
测试时使用中等长度字符串,对每个词使用的是32位BKDRHash算法,此次测试并未考虑上下文相关性,四个字符串分别为:
- S5:电视剧/小时代/由/郭敬明/的/同名/小说/改编/而/成/故事/以/经济/飞速/发展/的/上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照
- S6:电视剧/大时代/由/郭敬明/的/同名/小说/改编/而/成/该剧情/以/经济/飞速/发展/的/大上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照
- S7:你/妈妈/喊/你/回家/吃饭/哦/回家/喽/回家/喽
- S8:你/妈妈/叫/你/回家/吃饭/哦/回家/喽/回家/喽
未降维时四个字符串的SimHash值为(太长,截取了一部分):
降维后的SimHash值为:
计算各个字符串之间的海明距离:
从上可以看出,在这次测试的结果中,因为S5和S6本就是相似的(两个词不同),S7和S8本就是相似的(一个词不同),检测结果显示S5和S6、S7和S8之间的海明距离都非常小(1和0),而其他情况的海明距离就相对比较大了(因为根本很明显不是相似的),这与预期是相同的。
3.4 第四个测试A4
测试时使用中等长度字符串,对每个词使用的是32位BKDRHash算法,此次测试考虑上下文相关性(主要是与第三个测试A3做对比),四个字符串分别为:
- S5:电视剧/小时代/由/郭敬明/的/同名/小说/改编/而/成/故事/以/经济/飞速/发展/的/上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照
- S6:电视剧/大时代/由/郭敬明/的/同名/小说/改编/而/成/该剧情/以/经济/飞速/发展/的/大上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照
- S7:你/妈妈/喊/你/回家/吃饭/哦/回家/喽/回家/喽
- S8:你/妈妈/叫/你/回家/吃饭/哦/回家/喽/回家/喽
未降维时四个字符串的SimHash值为(太长,截取了一部分):
降维后的SimHash值为:
计算各个字符串之间的海明距离:
从上可以看出,在这次测试的结果中,因为S5和S6本就是相似的(两个词不同),S7和S8本就是相似的(一个词不同),检测结果显示S5和S6、S7和S8之间的海明距离都非常小(1和0),而其他情况的海明距离就相对比较大了(因为根本很明显不是相似的),这与预期是相同的。
另外,与第三次测试A3相比较,这次的结果与上次基本相同(相似的海明距离小,不相似的海明距离大),只是海明距离数值有差别而已。
3.5 第五个测试A5
以上四个测试(A1~A4)中,对每个词使用的都是32位BKDRHash算法,至于这一块需要使用哪一种Hash转换算法,在我查找的资料中并没有给出明确表示,只有在一篇文章中说“使用传统的Hash算法”,下面对这一块做测试,将分别使用RSHash、BKDRHash、DJBHash、JSHash和SDBMHash。
本次测试以第一个测试A1为基准,测试时使用短字符串,对每个词分别使用32位的RSHash、BKDRHash、DJBHash、JSHash和SDBMHash(至于这几种Hash算法,请参考我的另一篇文章《关于Hash的几种常用算法》),此次测试并未考虑上下文相关性,四个字符串分别为:
- S1:SimHash/算法/的/研究
- S2:SimHash/算法/的/探讨
- S3:SimHash/研究/的/算法
- S4:SimHash/是/一种/文本/相似性/算法
本次测试将只看以上四个字符串的SimHash值(降维后)和各个字符串之间的海明距离:
RSHash
BKDRHash
DJBHash
JSHash
SDBMHash
此次测试总结:之前我以为,不管使用哪种Hash算法对词转换,最后得到的字符串之间海明距离是由规律的(比如最小的还是最小,最大的还是最大),可事实证明,然后并没有。
3.6 第六个测试A6
在第五个测试A5中,并未考虑上下文相关性,本次测试考虑上下文相关性,再次对5钟Hash算法进行比较。
本次测试以第一个测试A1为基准,测试时使用短字符串,对每个词分别使用32位的RSHash、BKDRHash、DJBHash、JSHash和SDBMHash(至于这几种Hash算法,请参考我的另一篇文章《关于Hash的几种常用算法》),此次测试考虑上下文相关性(主要是与第五个测试A5做对比),四个字符串分别为:
- S1:SimHash/算法/的/研究
- S2:SimHash/算法/的/探讨
- S3:SimHash/研究/的/算法
- S4:SimHash/是/一种/文本/相似性/算法
本次测试将只看以上四个字符串的SimHash值(降维后)和各个字符串之间的海明距离:
RSHash
BKDRHash
DJBHash
JSHash
SDBMHash
此次测试总结:此次测试结合第五次测试A5,几乎证明了在对文本进行SimHash时,对每个词Hash转换所使用的Hash算法还是对结果会产生较大影响的,但至于使用哪一种Hash算法更准确,我目前还不太清楚。
3.7 第七个测试A7
从前几次测试中,不知读者是否发现一个现象:在不考虑文本上下文相关性的前提下(文本相同),计算得到的SimHash值较小;考虑文本上下文相关性后(文本相同),计算得到的SimHash值相对较大。这与所使用的Hash函数有直接的关系,但是还有一个因素->每个词的长度。
当对每个词进行Hash函数转换时,大多数Hash函数是根据词的长度进行循环累乘的,所以考虑文本上下文相关性后,词的长度变长了,计算所得的Hash值固然就变长了,进而也就影响了SimHash值的长度(所有词的Hash累加)。
以上分析都是在相同文本下两种情况所产生的SimHash长度,当然,SimHash长度主要还与文本的长度有关,在进行大文本处理时,累加所产生的长度变化也是要考虑的。下面一段程序是基于第一次测试A1扩展成的64位SimHash算法,但是前面那么多位的“0”好像并没有太大意义哦。
注:怎么产生64位呢?其实就是“int”和“long”的差别,在对每个词进行Hash函数转换时,所使用的数值类型不同而已。
1 /* 【算法】SimHash->64位 2 * 【说明】1.本程序手动分词,假设每个词的权重都为1 3 * 【说明】2.对每个词进行BKDRHash算法,在此基础上加减权重 4 * 【说明】3.将所有词整合后,降维 5 * 【说明】4.计算各个句子的海明距离 6 * 【时间】祁俊辉->2017.5.20 7 * */ 8 public class SimHash_64 { 9 //定义待比较的字符串 10 static String s1="SimHash/算法/的/研究"; 11 static String s2="SimHash/算法/的/探讨"; 12 static String s3="SimHash/研究/的/算法"; 13 static String s4="SimHash/是/一种/文本/相似性/算法"; 14 //定义待比较的字符串 15 static String s5="电视剧/小时代/由/郭敬明/的/同名/小说/改编/而/成/故事/以/经济/飞速/发展/的/上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照"; 16 static String s6="电视剧/大时代/由/郭敬明/的/同名/小说/改编/而/成/该剧情/以/经济/飞速/发展/的/大上海/这/座/风光/而/时尚/的/城市/为/背景/讲述/了/林萧/南湘/顾里/唐宛如/这/四/个/从小/感情/深厚/有着/不同/价值观/和/人生观/的/女生/先后/所/经历/的/友情/爱情/乃至/亲情/的/巨大/转变/是/一/部/当下/年轻人/生活/一个/侧面/的/真实/写照"; 17 //定义待比较的字符串 18 static String s7="你/妈妈/喊/你/回家/吃饭/哦/回家/喽/回家/喽"; 19 static String s8="你/妈妈/叫/你/回家/吃饭/哦/回家/喽/回家/喽"; 20 /* 函数名:BKDR_Hash(String str) 21 * 功能:计算字符串str的64位hash值,并将其以int型返回 22 * */ 23 static long BKDR_Hash(String str){ 24 int seed=131;//数乘因子 25 long hash=0; 26 for(int i=0;i<str.length();i++){ 27 hash=hash*seed+str.charAt(i); 28 //System.out.println(hash); 29 } 30 //return (hash & 0x7FFFFFFF);//32位 31 return (hash & 0x7FFFFFFFFFFFFFFFL);//64位 32 } 33 /* 函数名:First_FC(String str) 34 * 功能:1.先创建一个存储SimHash值的64数组,并初始化为0 35 * 功能:2.将str字符串分词,并存入临时数组 36 * 功能:3.计算此字符串的SimHash值(加权、但没有降维),存储在数组中 37 * 功能:4.将数组中的SimHash值降维,并以字符串形式返回 38 * */ 39 static String First_FC(String str){ 40 //1.先创建一个存储SimHash值的64数组,并初始化为0 41 int Hash_SZ[] = new int[64]; 42 for(int i=0;i<Hash_SZ.length;i++) 43 Hash_SZ[i]=0; 44 //2.将str字符串分词,并存入临时数组 45 String[] newstr = str.split("/"); 46 //下面的for循环是为了增加前后文关联性//即12/23/34/45··· 47 /*for(int i=0;i<newstr.length-1;i++){ 48 newstr[i]=newstr[i]+newstr[i+1]; 49 }*/ 50 //相应的,若增加上面的关联性语句,下面一行的代码要改为 51 //for(int i=0;i<newstr.length-1;i++){ 52 //3.计算此字符串的SimHash值(加权、但没有降维),存储在数组中 53 for(int i=0;i<newstr.length;i++){//循环传入字符串的每个词 54 long str_hash=BKDR_Hash(newstr[i]);//先计算每一个词的Hash值(64位) 55 //System.out.println(Integer.toBinaryString(str_hash)); 56 //对每个词的Hash值(32位)求j位是1还是0,1的话加上该词的权重,0的话减去该词的权重 57 for(int j=0;j<Hash_SZ.length;j++){ 58 long flag = (str_hash>>j)&1;//不要忘记上面计算的值是十进制,并不能直接知道j位是多少 59 //System.out.println(flag); 60 if(1 == flag){ 61 Hash_SZ[j]++;//权重先设置为1//Hash_SZ中,0是最低位,依次排高 62 }else{ 63 Hash_SZ[j]--; 64 } 65 } 66 } 67 //4.将数组中的SimHash值降维,并以字符串形式返回 68 String SimHash_number="";//存储SimHash值 69 for(int i=Hash_SZ.length-1;i>=0;i--){//从高位到低位 70 System.out.print(Hash_SZ[i]+" ");//输出未降维的串 71 if(Hash_SZ[i]<=0)//小于等于0,就取0 72 SimHash_number += "0"; 73 else//大于0,就取1 74 SimHash_number += "1"; 75 } 76 System.out.println("");//换行 77 return SimHash_number; 78 } 79 /* 函数名:HMJL(String a,String b) 80 * 功能:a、b都是以String存储的二进制数,计算他们的海明距离,并将其返回 81 * */ 82 static int HMJL(String a,String b){ 83 char[] FW1 = a.toCharArray();//将a每一位都存入数组中 84 char[] FW2 = b.toCharArray();//将b每一位都存入数组中 85 int haiming=0; 86 if(FW1.length == FW2.length){//确保a和b的位数是相同的 87 for(int i=0;i<FW1.length;i++){ 88 if(FW1[i] != FW2[i])//如果该位不同,海明距离加1 89 haiming++; 90 } 91 } 92 return haiming; 93 } 94 95 public static void main(String[] args) { 96 String a1 = First_FC(s1); 97 String a2 = First_FC(s2); 98 String a3 = First_FC(s3); 99 String a4 = First_FC(s4); 100 System.out.println("【s1】的SimHash值为:"+a1); 101 System.out.println("【s2】的SimHash值为:"+a2); 102 System.out.println("【s3】的SimHash值为:"+a3); 103 System.out.println("【s4】的SimHash值为:"+a4); 104 System.out.println("【s1】和【s2】的海明距离为:"+HMJL(a1,a2)); 105 System.out.println("【s1】和【s3】的海明距离为:"+HMJL(a1,a3)); 106 System.out.println("【s1】和【s4】的海明距离为:"+HMJL(a1,a4)); 107 System.out.println("【s2】和【s3】的海明距离为:"+HMJL(a2,a3)); 108 System.out.println("【s2】和【s4】的海明距离为:"+HMJL(a2,a4)); 109 System.out.println("【s3】和【s4】的海明距离为:"+HMJL(a3,a4)); 110 111 String a5 = First_FC(s5); 112 String a6 = First_FC(s6); 113 String a7 = First_FC(s7); 114 String a8 = First_FC(s8); 115 System.out.println("【s5】的SimHash值为:"+a5); 116 System.out.println("【s6】的SimHash值为:"+a6); 117 System.out.println("【s7】的SimHash值为:"+a7); 118 System.out.println("【s8】的SimHash值为:"+a8); 119 System.out.println("【s5】和【s6】的海明距离为:"+HMJL(a5,a6)); 120 System.out.println("【s5】和【s7】的海明距离为:"+HMJL(a5,a7)); 121 System.out.println("【s5】和【s8】的海明距离为:"+HMJL(a5,a8)); 122 System.out.println("【s6】和【s7】的海明距离为:"+HMJL(a6,a7)); 123 System.out.println("【s6】和【s8】的海明距离为:"+HMJL(a6,a8)); 124 System.out.println("【s7】和【s8】的海明距离为:"+HMJL(a7,a8)); 125 } 126 }
依然测试时使用短字符串,对每个词使用的是64位BKDRHash算法,此次测试并未考虑上下文相关性,四个字符串分别为:
- S1:SimHash/算法/的/研究
- S2:SimHash/算法/的/探讨
- S3:SimHash/研究/的/算法
- S4:SimHash/是/一种/文本/相似性/算法
未降维时四个字符串的SimHash值为(太长,截取了一部分):
降维后的SimHash值为:
计算各个字符串之间的海明距离:
从上可以看出,与第一次测试A1所产生的结果完全相同,无非就是前面加了几个“0”而已。
可以得出:在进行短文本计算时,完全没必要使用64位的SimHash算法。