每篇一句:
God made relatives.Thank God we can choose our friends. ——《加菲猫》
编辑距离算法简介:
定义:
设A和B是两个字符串。将字符串A转换为字符串B所用的最少字符操作数称为字符串A到字符串B的编辑距离。(这里所说的字符操作包括:删除一个字符,插入一个字符,修改一个字符)是由俄国科学家Levenshtein提出的,故又叫Levenshtein Distance 。(LD算法)基本性质:
1.LD(A,A)=02.LD(A,”“)=Len(A)
3.LD(A,B)=LD(B,A)
4.0≤LD(A,B)≤Max(Len(A),Len(B))
5.LD(A,B)=LD(Rev(A),Rev(B))
6.LD(A+C,B+C)=LD(A,B)
7.LD(A+B,A+C)=LD(B,C)
8.LD(A,B)≤LD(A,C)+LD(B,C)
9.LD(A+C,B)≤LD(A,B)+LD(B,C)
为了讲解计算LD(A,B), 给予一下几个定义:
A=a1a2…aN,表示A是由a1a2…aN这N个字符组成,Len(A)=N
B=b1b2…bN,表示B是由b1b2…bM这M个字符组成,Len(B)=M
定义LD(i, j)=LD(a1a2…ai, b1b2…bj),其中0<=N, 0<=M
故:- LD(N,M) = LD(A,B)
- LD(0,0) = 0
- LD(0,j) = j
- LD(i,0) = i
对于1<=i<=N, 1<=j<=M, 有公式一:
若ai=bj, 则LD(i, j) = LD(i-1, j-1)
若ai≠bj, 则LD(i, j) = Min(LD(i-1, j-1), LD(i-1, j), LD(i, j-1))+1简单例子:
A=GGATCGA
B=GAATTCAGTTA
将较短字符串A置于矩阵左侧,较长字符串B置于矩阵上侧:
第一步:根据公式一填充第一行结果G A A T T C A G T T A 0 1 2 3 4 5 6 7 8 9 10 11 G 1 0 1 2 3 4 5 6 7 8 9 10 G 2 A 3 T 4 C 5 G 6 A 7 第二步:填充其他表格,取最右下角的数字即为编辑距离。
G A A T T C A G T T A 0 1 2 3 4 5 6 7 8 9 10 11 G 1 0 1 2 3 4 5 6 7 8 9 10 G 2 1 1 2 3 4 5 6 6 7 8 9 A 3 2 1 1 2 3 4 5 6 7 8 8 T 4 3 2 2 1 2 3 4 5 6 7 8 C 5 4 3 3 2 2 2 3 4 5 6 7 G 6 5 4 4 3 3 3 3 3 4 5 6 A 7 6 5 4 4 4 4 3 4 4 5 5
python实现
具体解释说明见代码中注释
# coding=utf-8
# 这里的实现过程对算法进行了稍微的优化(运算结果应该稍快一些):首先计算两个字符串开头以及结尾
# 的共同字符子串,然后去掉相同部分,重新构造新字符串,减少迭代过程次数。
# 如:string_a = "GGATCGA" string_b = "GAATTCAGTTA"构造的新字符串为:
# new_a = "AATTCAGTT" new_b = "GATCG"
def LD(string_a, string_b):
diff_start = -1
diff_end = -1
len_a = len(string_a)
len_b = len(string_b)
short = min(len_a, len_b)
# 寻找开头和结尾的共同字符串,并记录位置
for i in range(0, short):
if string_a[i] != string_b[i]:
diff_start = i
break
if diff_start == -1:
return abs(len_b - len_a)
for i in range(0, short):
if string_a[len_a - i -1] != string_b[len_b - i - 1]:
diff_end = i
break
if diff_end == -1:
return abs(len_b - len_a)
# L(A+C, B+C) = LD(A, B)
# 出去开头以及结尾相同的字符串,构建新的字符串
long_str = unicode(string_a[diff_start: len_a - diff_end] if len_a >= len_b else string_b[diff_start: len_b - diff_end])
short_str = unicode(string_a[diff_start: len_a - diff_end] if len_a < len_b else string_b[diff_start: len_b - diff_end])
# print long_str
# print short_str
long_len = len(long_str)
short_len = len(short_str)
# store保存迭代过程中每次计算的结果
store = range(0, long_len + 1)
for i in range(short_len):
temp = [i+1] * (long_len + 1)
for j in range(long_len):
if long_str[j] == short_str[i]:
temp[j+1] = store[j]
else:
# 注意这时各个位置数据的对应关系
temp[j+1] = min(store[j], store[j+1], temp[j]) + 1
store = temp
# print store
# 最右下角即为编辑距离
return store[-1]
# Test
string_a = "GGATCGA"
string_b = "GAATTCAGTTA"
ld = LD(string_a, string_b)
print ld
写在后面:
以上即为LD算法的基本内容以及python实现,如果有什么错误或者改进意见,欢迎在下面评论或着私信博主。
代码下载:码云-LD算法的python实现