在搞验证码识别的时候需要比较字符代码的相似度用到“编辑距离算法”,关于原理和C#实现做个记录。
据百度百科介绍:
编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数,如果它们的距离越大,说明它们越是不同。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如将kitten一字转成sitting:
sitten (k→s)
sittin (e→i)
sitting (→g)
俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。因此也叫Levenshtein Distance。
例如
- 如果str1="ivan",str2="ivan",那么经过计算后等于 0。没有经过转换。相似度=1-0/Math.Max(str1.length,str2.length)=1
- 如果str1="ivan1",str2="ivan2",那么经过计算后等于1。str1的"1"转换"2",转换了一个字符,所以距离是1,相似度=1-1/Math.Max(str1.length,str2.length)=0.8
应用
DNA分析
拼字检查
语音辨识
抄袭侦测
算法过程
- str1或str2的长度为0返回另一个字符串的长度。 if(str1.length==0) return str2.length; if(str2.length==0) return str1.length;
- 初始化(n+1)*(m+1)的矩阵d,并让第一行和列的值从0开始增长。
- 扫描两字符串(n*m级的),如果:str1[i] == str2[j],用temp记录它,为0。否则temp记为1。然后在矩阵d[i,j]赋于d[i-1,j]+1 、d[i,j-1]+1、d[i-1,j-1]+temp三者的最小值。
- 扫描完后,返回矩阵的最后一个值d[n][m]即是它们的距离。
计算相似度公式:1-它们的距离/两个字符串长度的最大值。
为了直观表现,我将两个字符串分别写到行和列中,实际计算中不需要。我们用字符串“ivan1”和“ivan2”举例来看看矩阵中值的状况:
1、第一行和第一列的值从0开始增长
i | v | a | n | 1 | ||
0 | 1 | 2 | 3 | 4 | 5 | |
i | 1 | |||||
v | 2 | |||||
a | 3 | |||||
n | 4 | |||||
2 | 5 |
2、i列值的产生 Matrix[i - 1, j] + 1 ; Matrix[i, j - 1] + 1 ; Matrix[i - 1, j - 1] + t
i | v | a | n | 1 | ||
0+t=0 | 1+1=2 | 2 | 3 | 4 | 5 | |
i | 1+1=2 | 取三者最小值=0 | ||||
v | 2 | 依次类推:1 | ||||
a | 3 | 2 | ||||
n | 4 | 3 | ||||
2 | 5 | 4 |
3、V列值的产生
i | v | a | n | 1 | ||
0 | 1 | 2 | ||||
i | 1 | 0 | 1 | |||
v | 2 | 1 | 0 | |||
a | 3 | 2 | 1 | |||
n | 4 | 3 | 2 | |||
2 | 5 | 4 | 3 |
依次类推直到矩阵全部生成
i | v | a | n | 1 | ||
0 | 1 | 2 | 3 | 4 | 5 | |
i | 1 | 0 | 1 | 2 | 3 | 4 |
v | 2 | 1 | 0 | 1 | 2 | 3 |
a | 3 | 2 | 1 | 0 | 1 | 2 |
n | 4 | 3 | 2 | 1 | 0 | 1 |
2 | 5 | 4 | 3 | 2 | 1 | 1 |
最后得到它们的距离=1
相似度:1-1/Math.Max(“ivan1”.length,“ivan2”.length) =0.8
算法用C#实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<span style=
"color: #008080"
> 1</span> <span style=
"color: #0000ff"
>
public
</span> <span style=
"color: #0000ff"
>
class
</span><span style=
"color: #000000"
> LevenshteinDistance
</span><span style=
"color: #008080"
> 2</span> <span style=
"color: #000000"
> {
</span><span style=
"color: #008080"
> 3</span> <span style=
"color: #808080"
>
///</span> <span style="color: #808080"><summary></span>
<span style=
"color: #008080"
> 4</span> <span style=
"color: #808080"
>
///</span><span style="color: #008000"> 取最小的一位数
</span><span style=
"color: #008080"
> 5</span> <span style=
"color: #808080"
>
///</span> <span style="color: #808080"></summary></span>
<span style=
"color: #008080"
> 6</span> <span style=
"color: #808080"
>
///</span> <span style="color: #808080"><param name="first"></param></span>
<span style=
"color: #008080"
> 7</span> <span style=
"color: #808080"
>
///</span> <span style="color: #808080"><param name="second"></param></span>
<span style=
"color: #008080"
> 8</span> <span style=
"color: #808080"
>
///</span> <span style="color: #808080"><param name="third"></param></span>
<span style=
"color: #008080"
> 9</span> <span style=
"color: #808080"
>
///</span> <span style="color: #808080"><returns></returns></span>
<span style=
"color: #008080"
>10</span> <span style=
"color: #0000ff"
>
private
</span> <span style=
"color: #0000ff"
>
int
</span> LowerOfThree(<span style=
"color: #0000ff"
>
int
</span> first, <span style=
"color: #0000ff"
>
int
</span> second, <span style=
"color: #0000ff"
>
int
</span><span style=
"color: #000000"
> third)
</span><span style=
"color: #008080"
>11</span> <span style=
"color: #000000"
> {
</span><span style=
"color: #008080"
>12</span> <span style=
"color: #0000ff"
>
int
</span> min =<span style=
"color: #000000"
> Math.Min(first, second);
</span><span style=
"color: #008080"
>13</span> <span style=
"color: #0000ff"
>
return
</span><span style=
"color: #000000"
> Math.Min(min, third);
</span><span style=
"color: #008080"
>14</span> <span style=
"color: #000000"
> }
</span><span style=
"color: #008080"
>15</span>
<span style=
"color: #008080"
>16</span> <span style=
"color: #0000ff"
>
private
</span> <span style=
"color: #0000ff"
>
int
</span> Levenshtein_Distance(<span style=
"color: #0000ff"
>
string
</span> str1, <span style=
"color: #0000ff"
>
string
</span><span style=
"color: #000000"
> str2)
</span><span style=
"color: #008080"
>17</span> <span style=
"color: #000000"
> {
</span><span style=
"color: #008080"
>18</span> <span style=
"color: #0000ff"
>
int
</span><span style=
"color: #000000"
>[,] Matrix;
</span><span style=
"color: #008080"
>19</span> <span style=
"color: #0000ff"
>
int
</span> n =<span style=
"color: #000000"
> str1.Length;
</span><span style=
"color: #008080"
>20</span> <span style=
"color: #0000ff"
>
int
</span> m =<span style=
"color: #000000"
> str2.Length;
</span><span style=
"color: #008080"
>21</span>
<span style=
"color: #008080"
>22</span> <span style=
"color: #0000ff"
>
int
</span> temp = <span style=
"color: #800080"
>0</span><span style=
"color: #000000"
>;
</span><span style=
"color: #008080"
>23</span> <span style=
"color: #0000ff"
>
char
</span><span style=
"color: #000000"
> ch1;
</span><span style=
"color: #008080"
>24</span> <span style=
"color: #0000ff"
>
char
</span><span style=
"color: #000000"
> ch2;
</span><span style=
"color: #008080"
>25</span> <span style=
"color: #0000ff"
>
int
</span> i = <span style=
"color: #800080"
>0</span><span style=
"color: #000000"
>;
</span><span style=
"color: #008080"
>26</span> <span style=
"color: #0000ff"
>
int
</span> j = <span style=
"color: #800080"
|