[随笔]初步了解 Levenshtein Distance (Edit Distance) 编辑距离,字符相似度算法

前几天在CSDN的论坛看到一个需要判断两个字符串之间相差多少个字符的帖子,之前有了解过有相应的算法来计算这个差异,但是没有深入的去了解.刚好趁这个时机了解了一下: Levenshtein Distance (Edit Distance) 编辑距离,字符相似度算法

 

对于该算法,详细说明可参考wiki: 

 

摘自维基:

编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

 

例如将kitten一字转成sitting:

  1. sitten (k→s)
  2. sittin (e→i)
  3. sitting (→g)

 

俄罗斯科学家Vladimir Levenshtein1965年提出这个概念。

 

中文: http://zh.wikipedia.org/wiki/%E7%B7%A8%E8%BC%AF%E8%B7%9D%E9%9B%A2

英文: http://en.wikipedia.org/wiki/Levenshtein_distance 

 

然后写了一个Demo来加深了解

 

这里是维基给的伪代码:

 

动态规划经常被用来作为这个问题的解决手段之一。

整数 Levenshtein距离(字符 str1[1..lenStr1], 字符 str2[1..lenStr2])

   宣告 int d[0..lenStr1, 0..lenStr2]

   宣告 int i, j, cost

 

   对于 i 等于 由 0 至 lenStr1

       d[i, 0] := i

   对于 j 等于 由 0 至 lenStr2

       d[0, j] := j

   对于 i 等于 由 1 至 lenStr1

       对于 j 等于 由 1 至 lenStr2

           若 str1[i] = str2[j] 则 cost := 0

                                否则 cost := 1

           d[i, j] := 最小值(

                                d[i-1, j  ] + 1,     // 删除

                                d[i  , j-1] + 1,     // 插入

                                d[i-1, j-1] + cost   // 替换

                            )

 

   返回 d[lenStr1, lenStr2]

 

Demo如下:

 

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { char[] c1 = richTextBox1.Text.Trim().ToCharArray(); char[] c2 = richTextBox2.Text.Trim().ToCharArray(); int[,] result = Calculate(c1, c2); DataTable dt = new DataTable(); for (int i = 0; i < c1.Length + 2; i++) { dt.Columns.Add(i.ToString()); } for (int i = 0; i < c2.Length + 2; i++) { DataRow row = dt.NewRow(); dt.Rows.Add(row); } for (int i = 0; i < c2.Length + 2; i++) { if (i < 2) { dt.Rows[i][0] = string.Empty; } else { dt.Rows[i][0] = c2[i – 2]; } } for (int i = 0; i < c1.Length + 2; i++) { if (i < 2) { dt.Rows[0][i] = string.Empty; } else { dt.Rows[0][i] = c1[i – 2]; } } for (int i = 0; i < result.GetLength(0); i++) { for (int j = 0; j < result.GetLength(1); j++) { dt.Rows[j + 1][i + 1] = result[i, j]; } } if (checkBox1.Checked == true) { dataGridView1.DataSource = dt; dataGridView1.ColumnHeadersVisible = false; dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; } label1.Text = string.Format(“字符相似度:{0}” , dt.Rows[result.GetLength(1)][result.GetLength(0)].ToString()); } public static int[,] Calculate(char[] First, char[] Second) { int lenFirst = First.Length + 1; int lenSecond = Second.Length + 1; int[,] matrixResult = new int[lenFirst, lenSecond]; for (int i = 0; i < lenFirst; i++) matrixResult[i, 0] = i; for (int j = 0; j < lenSecond; j++) matrixResult[0, j] = j; for (int i = 1; i < lenFirst; i++) { for (int j = 1; j < lenSecond; j++) { if (First[i – 1] == Second[j – 1]) { matrixResult[i, j] = matrixResult[i – 1, j – 1]; } else { matrixResult[i, j] = new int[] {matrixResult[i – 1, j] + 1 , matrixResult[i , j-1] + 1 , matrixResult[i – 1, j-1] + 1 }.Min(); } } } return matrixResult; } } }

点赞