前几天在CSDN的论坛看到一个需要判断两个字符串之间相差多少个字符的帖子,之前有了解过有相应的算法来计算这个差异,但是没有深入的去了解.刚好趁这个时机了解了一下: Levenshtein Distance (Edit Distance) 编辑距离,字符相似度算法
对于该算法,详细说明可参考wiki:
摘自维基:
“编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如将kitten一字转成sitting:
- sitten (k→s)
- sittin (e→i)
- sitting (→g)
俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。“
中文: 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; } } }