1.查找一篇重复文本。前一段时间做过测试,Google的SimHash算法效果还是不错的,文本长度与一篇论文长度差不多。
步骤为: a. 给整篇文档分词 term ,分词用的是IKAnalyzer。
b.计算每个分词term的MD5 哈希值。由于比较的文本长度不大,所以采用的是32位哈希。原本的MD5是直 接生成32位哈希的,16位的就是截取中间32位。代码如下:
public String Md5(String plainText ) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(plainText.getBytes()); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if(i<0) i+= 256; if(i<16) buf.append("0"); buf.append(Integer.toHexString(i)); } System.out.println("result(32位): " + buf.toString());//32位的加密 System.out.println("result(16位): " + buf.toString().substring(8,24));//16位的加密 return buf.toString().substring(8,24); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } }
c. SimHash计算的是全部MD5哈希的最后哈希值。算法思路是:
1,将一个f维的向量V初始化为0;f位的二进制数S初始化为0; 2,对每一个特征:用传统的hash算法对该特征产生一个f位的签名b。对i=1到f: 如果b的第i位为1,则V的第i个元素加上该特征的权重; 否则,V的第i个元素减去该特征的权重。 3,如果V的第i个元素大于0,则S的第i位为1,否则为0; 4,输出S作为签名
用一篇文档测试,Google SimHash用汉明距离度量。通常是汉明距离小于5即可认为两篇文档重复。我取为10的时候发现出现多篇文档,但是内容上却相差很大。具体的细节就不写了。
2.段落比较采用的是计算段落每个分词term的tfidf值,然后匹配。为了提高效率,我假设匹配之前已经清楚该文档所属分类。
用tfidf可以确定的找到测试文档的出处。十分准确。不像SimHash会出现不相干的文档。