编辑距离

Levenshtein distance

Posted by BY on October 31, 2018

前言

今天是10月的最后一天,把10月没写的博客给补上。

正文

问题来源

最近在看etcd相关的源码,其中该源码用到cobra框架,看cobra的时候看到了编辑距离这个算法。以前在笔试的时候遇到过这个问题,当时也没有怎么认真的对待,今天就好好看看。

问题描述

两个单词之间的编辑距离(Levenshtein distance)是将一个单词更改为另一个单词所需的单字符编辑(插入,删除或替换)的最小次数。

示例

举个栗子,将eeba转变成abac:
① eba(删除第一个e)
② aba(将剩下的e替换成a)
③ abac(在末尾插入c)
所以eeba和abac的编辑距离就是3

分析:

详细请看维基百科Levenshtein distance

状态转移方程:


           lev(i-1,j-1)                            Sa[i] == Sb[j]
lev(i,j)=  
           min(lev(i-1,j-1),lev(i-1,j),lev(i,j-1))  Sa[i] != Sb[j]

Sa,Sb为两字符串

Cobra中的算法:

// ld compares two strings and returns the levenshtein distance between them.
func ld(s, t string, ignoreCase bool) int {
	if ignoreCase {
		s = strings.ToLower(s)
		t = strings.ToLower(t)
	}
	d := make([][]int, len(s)+1)
	for i := range d {
		d[i] = make([]int, len(t)+1)
	}
	for i := range d {
		d[i][0] = i
	}
	for j := range d[0] {
		d[0][j] = j
	}
	for j := 1; j <= len(t); j++ {
		for i := 1; i <= len(s); i++ {
			if s[i-1] == t[j-1] {
				d[i][j] = d[i-1][j-1]
			} else {
				min := d[i-1][j]
				if d[i][j-1] < min {
					min = d[i][j-1]
				}
				if d[i-1][j-1] < min {
					min = d[i-1][j-1]
				}
				d[i][j] = min + 1
			}
		}

	}
	return d[len(s)][len(t)]
}

该算法用在检查用户输入的命令不存在时,返回相类似的命令。

总结:

多看源码,增长见识

结语

不要懒,多看多写。