字符串相似度算法(Levenshtein Distance)

Levenshtein Distance(LD)算法是比较两字符串的相似性。它们的距离就是一个字符串转换成那一个字符串过程中的添加、删除、修改数值,如果s是源字符串souce,t是目标字符串target,比较s和t是否相似,如下:

  • 如果s="test",t="test",那么LD(str1,str2) = 0。没有经过转换。

  • 如果s="test",t="tent",那么LD(str1,str2) = 1。str1的"s"转换"n",转换了一个字符,所以是1。如果它们的距离越大,说明它们越不同。

    Levenshtein distance最先是由俄国科学家Vladimir Levenshtein在1965年发明,用他的名字命名。

    Levenshtein distance可以用来:

  • Spell checking(拼写检查)

  • Speech recognition(语句识别)

  • DNA analysis(DNA分析)

  • Plagiarism detection(抄袭检测)

LD算法大概过程:

Steps

Step

Description

1

Set n to be the length of s.
Set m to be the length of t.
If n = 0, return m and exit.
If m = 0, return n and exit.
Construct a matrix containing 0..m rows and 0..n columns.

2

Initialize the first row to 0..n.
Initialize the first column to 0..m.

3

Examine each character of s (i from 1 to n).

4

Examine each character of t (j from 1 to m).

5

If s[i] equals t[j], the cost is 0.
If s[i] doesn't equal t[j], the cost is 1.

6

Set cell d[i,j] of the matrix equal to the minimum of:
a. The cell immediately above plus 1: d[i-1,j] + 1.
b. The cell immediately to the left plus 1: d[i,j-1] + 1.
c. The cell diagonally above and to the left plus the cost: d[i-1,j-1] + cost.

7

After the iteration steps (3, 4, 5, 6) are complete, the distance is found in cell d[n,m]


distance头文件

  1. class Distance
  2. {
  3.   public:
  4.     int LD (char const *s, char const *t);
  5.   private:
  6.     int Minimum (int a, int b, int c);
  7.     int *GetCellPointer (int *pOrigin, int col, int row, int nCols);
  8.     int GetAt (int *pOrigin, int col, int row, int nCols);
  9.     void PutAt (int *pOrigin, int col, int row, int nCols, int x);
  10. }; 

distance代码文件
  1. #include "distance.h"
  2. #include <string.h>
  3. #include <malloc.h>
  4. //****************************
  5. // Get minimum of three values
  6. //****************************
  7. int Distance::Minimum (int a, int b, int c)
  8. {
  9. int mi;
  10.   mi = a;
  11.   if (b < mi) {
  12.     mi = b;
  13.   }
  14.   if (c < mi) {
  15.     mi = c;
  16.   }
  17.   return mi;
  18. }
  19. //**************************************************
  20. // Get a pointer to the specified cell of the matrix
  21. //************************************************** 
  22. int *Distance::GetCellPointer (int *pOrigin, int col, int row, int nCols)
  23. {
  24.   return pOrigin + col + (row * (nCols + 1));
  25. }
  26. //*****************************************************
  27. // Get the contents of the specified cell in the matrix 
  28. //*****************************************************
  29. int Distance::GetAt (int *pOrigin, int col, int row, int nCols)
  30. {
  31. int *pCell;
  32.   pCell = GetCellPointer (pOrigin, col, row, nCols);
  33.   return *pCell;
  34. }
  35. //*******************************************************
  36. // Fill the specified cell in the matrix with the value x
  37. //*******************************************************
  38. void Distance::PutAt (int *pOrigin, int col, int row, int nCols, int x)
  39. {
  40. int *pCell;
  41.   pCell = GetCellPointer (pOrigin, col, row, nCols);
  42.   *pCell = x;
  43. }
  44. //*****************************
  45. // Compute Levenshtein distance
  46. //*****************************
  47. int Distance::LD (char const *s, char const *t)
  48. {
  49. int *d; // pointer to matrix
  50. int n; // length of s
  51. int m; // length of t
  52. int i; // iterates through s
  53. int j; // iterates through t
  54. char s_i; // ith character of s
  55. char t_j; // jth character of t
  56. int cost; // cost
  57. int result; // result
  58. int cell; // contents of target cell
  59. int above; // contents of cell immediately above
  60. int left; // contents of cell immediately to left
  61. int diag; // contents of cell immediately above and to left
  62. int sz; // number of cells in matrix
  63.   // Step 1 
  64.   n = strlen (s);
  65.   m = strlen (t);
  66.   if (n == 0) {
  67.     return m;
  68.   }
  69.   if (m == 0) {
  70.     return n;
  71.   }
  72.   sz = (n+1) * (m+1) * sizeof (int);
  73.   d = (int *) malloc (sz);
  74.   // Step 2
  75.   for (i = 0; i <= n; i++) {
  76.     PutAt (d, i, 0, n, i);
  77.   }
  78.   for (j = 0; j <= m; j++) {
  79.     PutAt (d, 0, j, n, j);
  80.   }
  81.   // Step 3
  82.   for (i = 1; i <= n; i++) {
  83.     s_i = s[i-1];
  84.     // Step 4
  85.     for (j = 1; j <= m; j++) {
  86.       t_j = t[j-1];
  87.       // Step 5
  88.       if (s_i == t_j) {
  89.         cost = 0;
  90.       }
  91.       else {
  92.         cost = 1;
  93.       }
  94.       // Step 6 
  95.       above = GetAt (d,i-1,j, n);
  96.       left = GetAt (d,i, j-1, n);
  97.       diag = GetAt (d, i-1,j-1, n);
  98.       cell = Minimum (above + 1, left + 1, diag + cost);
  99.       PutAt (d, i, j, n, cell);
  100.     }
  101.   }
  102.   // Step 7
  103.   result = GetAt (d, n, m, n);
  104.   free (d);
  105.   return result;
  106.     
  107. }

posted on 2010-12-05 22:38  ATAK  阅读(411)  评论(0编辑  收藏  举报

导航