声明:本项目在deepin系统下vim编译的,利用了jieba分词工具,如果在vs编译的话需要设置文件路径,还需要把GDK转成UTF8,在读的时候用UTF8转成GDK
1.文件查重原理:
1.1中文分词:
虽然使用的是jieba分词,但是我们可以多了解一点,便于以后的扩展:
三大主流分词方法:基于词典的方法、基于规则的方法和基于统计的方法。
1.1.1、分词目的:用于计算文本相似度
- 按照扫描方向的不同:正向匹配和逆向匹配
- 按照长度的不同:最大匹配和最小匹配
1.1.3、基于统计的分词:
- 主要思想:把每个词看做是由词的最小单位各个字总成的,如果相连的字在不同的文本中出现的次数越多,就证明这相连的字很可能就是一个词。因此我们就可以利用字与字相邻出现的频率来反应成词的可靠度,统计语料中相邻共现的各个字的组合的频度,当组合频度高于某一个临界值时,我们便可认为此字组可能会构成一个词语。
- 主要统计模型:N元文法模型(N-gram),隐马尔可夫模型(Hidden Markov Model ,HMM),最大熵模型(ME),条件随机场模型(Conditional Random Fields,CRF)等。
具体知识参考:https://blog.csdn.net/mingzai624/article/details/51698643;(这里我们就不做这个步骤了,就利用现成的jieba,有兴趣的可以自己实现一个分词工具)
分词工具的下载:
- Jieba (C++, Java, python)https://github.com/fxsjy/jieba
- LTP (C++, Java, python)https://github.com/HIT-SCIR/ltp
1.2词频统计:
- 词频即为单词在文章中出现的次数。
- 词频的大小一般可以反映一个词在一篇文章中的重要性,词频越大,可以认为该词越重要。
- 一片文章的语义可以由一组关键词简要概括,比如“爱上一个人”,这里停顿不一样就不一样。”爱“,”上“,”一个人“:就是想那个啥嗯嗯。”爱“,”上一个人“可以理解为喜欢之前的一个人,或者就是喜欢现在一个人。这里就体现上一个步骤的重要性了,分好了,这一步就根据符合可以区分
代码中利用jieba分词中提供的停用词工具和语义替换成/,让我们跟好的可以统计词频
1.3文本相似度的计算公式:
1.3.1 基于关键词匹配:
-
N-gram 相似度:
Similarity=|GN(S)|+|GN(T)|−2∗|GN(S)∩GN(T)|
-
Jaccard 相似度:
J(A,B)=|A∩B||A∪B|
1.3.2 基于向量空间:
- Word2vec
- TF-IDF
- 相似度计算
- 欧式距离
- 曼哈顿距离
- 余弦相似度(我用的这种方法):余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。
跟详细的文本相似度的算法请参考:https://blog.csdn.net/qq_28031525/article/details/79596376
2.源码分析:
有段没有注释的是引用jieba的,然后其他的每个函数的功能都有注释。这里我们首先分析一下我们肯定需要一个统计词频的容器,在STL中unordered_map最为合适:
- 1.它有一个key值,一个value值,可以正好可以用来放词和词频。
- 2.它底层是哈希实现的所有查找速率很快,而这个功能对于我们来说很适合。
而unordered_set有个功能是我们需要的就是它有去重的功能cound
- 1.这个可以帮助我