当前位置: 首页 > article >正文

文本相似度检查实现

在这里插入图片描述

最近需要做一个文章标题相似度检测提醒,所以了解一下相关的算法,整理如下。

Hamming Distance 汉明距离

汉明距离是一个概念,它表示两个(相同长度)字符串对应位置的不同字符的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。
1011101 与 1001001 之间的汉明距离是 2。
2143896 与 2233796 之间的汉明距离是 3。
“toned” 与 “roses” 之间的汉明距离是 3。

function hamingString(str1: string, str2: string) {if (str1.indexOf(str2) >= 0)return str1.length - str2.lengthif (str2.indexOf(str1) >= 0)return str2.length - str1.lengthlet diffCount = 0let minLen = 0if (str2.length < str1.length) {diffCount = str1.length - str2.lengthminLen = str2.length}else {diffCount = str2.length - str1.lengthminLen = str1.length}for (let i = 0; i < minLen; i++) {if (str1[i] != str2[i])diffCount++}return diffCount
}

算法介绍
比较两个字符串中最短的那个,从左开始循环比较,循环长度是最短的字符的长度。
汉明距离就是差异个数加上两个字符串的长度差
汉明距离算法有个很大的缺点,左边相同时有效,如果从左边插入一个不同的字符,则结果完全不同。
比如
字符A:我今天吃的很饱
字符B:我今天吃的很饱呢
A和B的汉明距离是1

字符A:我今天吃的很饱
字符B:看我今天吃的很饱
A和B的汉明距离是8,会认为两个完全不同。
但上面两种情况,我们都会认为是文本重复,但无法根据汉明距离准确去判定。

simhash算法

simhash算法介绍
simhash针对文本的话,k值敏感,一般选取3。认为汉明距离小于3的文本是相似的。
**缺点:**完全无关的文本正好对应成了相同的simhash,精确度并不是很高,而且simhash更适用于较长的文本,但是在大规模语料进行去重时,simhash的计算速度优势还是很不错的。

google的排重就是使用simhash算法实现的。
simhash算法适用于较长文本,大量文本,由于我们现在需求是判断文章标题雷同,所以暂时不深入研究。

最长公共子序列 LCS

最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

应用

最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的“相似度”,即它们的雷同程度,从而能够用来辨别抄袭。对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,这种方法判断修改的部分,往往十分准确。

def checkSimilarTitle(ret, englishName, name):'''判断标题相似'''calcList = {}for i in range(0, len(ret['data']['items'])):title = ret['data']['items'][i]['title']if ('username' in ret['data']['items'][i]['user']) == False:continueuserName = ret['data']['items'][i]['user']['username']md5 = getMd5(title)for j in range(0, len(ret['data']['items'])):title2 = ret['data']['items'][j]['title']point = longestCommonSubsequence(title, title2)if (len(title) + len(title2)) / 2 == 0:continue# 最长公共子序列的长度除以平均长度point = point / ((len(title) + len(title2)) / 2)# print(title, title2, point)# 这里的限定值需要测算,目前看情况0.7比较合适,大于等于0.7认为是重复if point >= 0.7:if md5 in calcList:calcList[md5] = {"point": calcList[md5]['point'] +1, "title": title, "userName": userName}else:calcList[md5] = {"point": 1,"title": title, "userName": userName}text = ''for key in calcList:if calcList[key]['point'] >= 3:text += f"标题:{calcList[key]['title']} 相似数量:{calcList[key]['point']} 发贴人:{calcList[key]['userName']}  \n"def longestCommonSubsequence(text1, text2):'''最长公共子序列查找'''s1, s2 = len(text1), len(text2)dp = [[0] * (s2 + 1) for _ in range(s1 + 1)]for i in range(1, s1 + 1):for j in range(1, s2 + 1):dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])if text1[i - 1] == text2[j - 1]:dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1)return dp[-1][-1]

测试示例

    text1 = '你好啊'text2 = '你好啊啊'val = longestCommonSubsequence(text1, text2)print(val)输出
3text1 = '今天天气真不错,适合外出玩'text2 = '今天玩了一下午,只吃了一个汉堡包'val = longestCommonSubsequence(text1, text2)print(val)输出
3

上面两个例子,最长公共子序列长度都是3,但是很明显第一个才是我们认为重复的文本,第二个明显不是。
所以判断的依据应该是最长公共子序列长度除以比较文本的平均长度,暂时命名叫:重复比,就是重复的文本长度占原标题文本长度的多少
比如占到70%以上,即认为是两个文本重复。

    text1 = '你好啊'text2 = '你好啊啊'val = longestCommonSubsequence(text1, text2)point = val / ((len(text1) + len(text2)) / 2)print(val, point)输出
3 0.8571428571428571text1 = '今天天气真不错,适合外出玩'text2 = '今天玩了一下午,只吃了一个汉堡包'val = longestCommonSubsequence(text1, text2)point = val / ((len(text1) + len(text2)) / 2)print(val, point)输出
3 0.20689655172413793

很明显,根据第一个重复比,0.85就可以判定文本重复。

总结

最后我是用最长公共子序列完成了需求,其他两种算法,暂时不适合于本需求。

http://www.lryc.cn/news/2419402.html

相关文章:

  • Codeforces Round #168 (Div. 2) B. Convex Shape(BFS || 模拟)
  • [19/03/16-星期六] 常用类_Date时间类DateFormat类
  • LC滤波器设计学习笔记(一)滤波电路入门
  • adb bugreport :查看设备所有信息(获取错误报告)
  • android gallery3d 源码分析(一)
  • Winpcap的安装使用方法
  • 【论文笔记】Progressive Layered Extraction (PLE): A Novel Multi-Task Learning (MTL) Model for Personalized
  • iptables/netfilter/iproute2/ip/tc/qdisc经常被混淆的几个概念
  • 调色盘管理器
  • 熊猫烧香专杀工具的编写
  • 鱼哭了,水知道。我哭了,谁知道
  • 天虹办公系统kk服务器,客户齐点赞,蓝凌KK 7.0大幅提升工作效率
  • 老牌技术员系统更新啦!(x86/x64)装机版/纯净版 2016.08
  • 都掏出来了,大学四年珍藏的26个宝藏网站,全部整理好给大家!!!_珍藏网页 -广告
  • 认识处理器(CPU)
  • wifi-加载驱动
  • CryENGINE3系列总结教程之UI/HUD(一)制作生命条弹药条Flash部分
  • Maple 入门常用教程
  • 验证手机号码归属地_手机号码怎么查找位置
  • Linux磁盘管理系列 — 磁盘配额管理
  • 三大工厂模式的优缺点
  • UI控件之UIControl
  • .net 微服务实践
  • web程序生成excel
  • 推荐:音速启动(快捷方式分类管理工具)
  • 四大作用域
  • 关于FL Studio ASIO驱动不工作的一个解决方案
  • 智能魔法棒(手势控制器)———嵌入式篇
  • Mac OSX 卸载PKG包
  • uushare第二版功能详细介绍