编辑距离算法应用总结

  项目中应用了编辑距离算法解决问题,做个总结。作为业务团队的同学,平时应用算法解决问题的机会并不多,但是还是要有这个能力 / 思维,对技术架构 / 技术选型都有帮助,遇到算法资源不足的情况,也能顶上。编辑距离算法可以用于衡量文本相似度,进而解决文本的模糊搜索 / 匹配问题。编辑距离又叫 Levenshtein 距离(莱文斯坦距离),区别于汉明距离(等长字符串对应位置的不同字符的个数),不仅可以替换字符,还可以增删字符。算法时间复杂度是 O(m*n),如果文本数量(t)较大,遍历文本集合,计算关键字和文本 Pair 的编辑距离,再做 TOP_K 遴选,时间复杂度为 O(m*n*t + logt*t),当 t 较大时将会存在性能问题。这个性能问题的一种解法是将莱文斯坦距离降级为汉明距离,不考虑增减字符的情况,用利用 LSH 算法的思想进行分桶匹配,快速锁定一些桶,只匹配这些桶内的文本,也就是快速排除一些桶,减少匹配次数,从而提升速度。(LSH 算法的应用下次展开)。在我的项目中,文本数量在 1w 左右,并且我们通过边缘计算的方式化解服务器的负载压力,最终还是应用编辑距离算法解决我们业务的文本模糊匹配问题。

  编辑距离算法是个经典 DP (动态规划)问题。完美契合 DP 问题的两大特征,一是问题可分解为规模更小的子问题,二是子问题解之间存在推导关系。对于编辑距离求解问题,我们把 S1(长度 m ) 和 S2 (长度 n) 的编辑距离定义为 d(m, n),用 d(m-1, n) 表示 S1 的子串(移除最后一个字符)和 S2 之间的编辑距离,同理定义 d(m, n-1) 、d(m-1, n-1),那么问题解之间的推导关系为,d(m, n) = d(m-1, n-1) if S1[m-1] == S2[n-1],d(m, n) = min(d(m-1, n), d(m, n-1)) + 1 if S1[m-1] != S2[n-1]。基本原理就是这样。

  在实际应用的时候,我们一是对空间复杂度进行了优化(常规优化操作),二是微调算法满足业务需要的特定匹配规则。一,我们的直接反应会使用一个 m*n 的二维数据存储解空间,空间复杂度是 O(m*n),但仔细观察一下,在推导过程中,新一行的解只依赖上一行的解,意味着我们可以只存储上一行的解,空间复杂度可以降为 O(n)。二,在我们的项目中,S1 是一个段落,S2 是关键字,我们的编辑距离并不是严格意义上的编辑距离,严格来说,我们业务需要的是 S1 的连续子串和 S2 的编辑距离,(听起来问题复杂了好多),(业务含义是这个段落里是不是包含了疑似 S2 的子串)。理解起来,S1 的连续子串和 S2 的编辑距离,可以转化为 S1 向 S2 转化(编辑 / 匹配)的过程,S1 的前缀、后缀可以不参与匹配,或者说可以自由删除 S1 的前缀、后缀,而不增加编辑距离,这样的话,我们对算法的微调方法就出来了,1,初始化时,d(i, 0) = 0, 0 <= i < m,表示可以删除 S1 的前缀而不增加编辑距离,2,求解最终解时,取 min(d(i, n)), 0 <= i < m,表示可以删除 S1 的后缀而不增加编辑距离。

你可能感兴趣的:(算法)