計算字符串相似度算法——Levenshtein

1.百度百科介紹:

Levenshtein 距離,又稱編輯距離,指的是兩個字符串之間,由一個轉換成另一個所需的最少編輯操作次數。

許可的編輯操作包括將一個字符替換成另一個字符,插入一個字符,刪除一個字符。

編輯距離的算法是首先由俄國科學家Levenshtein提出的,故又叫Levenshtein Distance。

2.用途

模糊查詢

3.實現過程

a.首先是有兩個字符串,這裏寫一個簡單的 abc和abe

b.將字符串想象成下面的結構。

A處 是一個標記,爲了方便講解,不是這個表的內容。

 


abcabc
abe0123
a1A處

b2


e3


c.來計算A處 出得值

它的值取決於:左邊的1、上邊的1、左上角的0.

按照Levenshtein distance的意思:

上面的值和左面的值都要求加1,這樣得到1+1=2。

A處 由於是兩個a相同,左上角的值加0.這樣得到0+0=0。

這是後有三個值,左邊的計算後爲2,上邊的計算後爲2,左上角的計算爲0,所以A處 取他們裏面最小的0.

d.於是表成爲下面的樣子


abcabc
abe0123
a10

b2B處

e3


B處 會同樣得到三個值,左邊計算後爲3,上邊計算後爲1,在B處 由於對應的字符爲a、b,不相等,所以左上角應該在當前值的基礎上加1,這樣得到1+1=2,在(3,1,2)中選出最小的爲B處的值。

e.於是表就更新了

 


abcabc
abe0123
a10

b21

e3C處

C處 計算後:上面的值爲2,左邊的值爲4,左上角的:a和e不相同,所以加1,即2+1,左上角的爲3。

在(2,4,3)中取最小的爲C處 的值。

f.於是依次推得到



abc

0123
a1A處 0D處 1G處 2
b2B處 1E處 0H處 1
e3C處 2F處 1I處 1

 

I處: 表示abc 和abe 有1個需要編輯的操作。這個是需要計算出來的。

同時,也獲得一些額外的信息。

A處: 表示a      和a      需要有0個操作。字符串一樣

B處: 表示ab    和a      需要有1個操作。

C處: 表示abe  和a      需要有2個操作。

D處: 表示a      和ab    需要有1個操作。

E處: 表示ab    和ab    需要有0個操作。字符串一樣

F處: 表示abe  和ab    需要有1個操作。

G處: 表示a      和abc   需要有2個操作。

H處: 表示ab    和abc    需要有1個操作。

I處: 表示abe   和abc    需要有1個操作。

g.計算相似度

先取兩個字符串長度的最大值maxLen,用1-(需要操作數除maxLen),得到相似度。

例如abc 和abe 一個操作,長度爲3,所以相似度爲1-1/3=0.666。

4.lua代碼實現

  1. strA = {"今", “天”, “是”, “星”, “期”, “四”}

  2. strB = {"今", “天”, “是”, “星”, “期”,“(”, “四”, “)”}

  3. 結果是75%


  4. function levenshtein(strA, strB)

  5.    local tempTb = {}

  6.    for m = 1, (#strA + 1), 1 do

  7.        tempTb[m] = {}

  8.        tempTb[m][1] = m - 1

  9.    end


  10.   for n = 1, (#strB + 1), 1 do

  11.     tempTb[1][n] = n - 1

  12.   end


  13.   for i = 2, (#strA + 1) , 1 do

  14.     for j = 2, (#strB + 1), 1 do

  15.         local x = tempTb[i - 1][j] + 1    --刪除

  16.         local y = tempTb[i][j - 1] + 1    --插入

  17.         local z = 0

  18.         if strA[i - 1] == strB[j - 1] then  --替換

  19.             z = tempTb[i -1][j - 1]

  20.         else

  21.             z = tempTb[i -1][j - 1] + 1

  22.         end

  23.        tempTb[i][j] = math.min(x,y,z)

  24.     end

  25.   end

  26.   return (1- tempTb[#strA + 1][#strB + 1]/math.max(#strA, #strB))*100

  27. end

5.猜測原理

爲什麼這樣就能算出相似度了?

首先在連續相等的字符就可以考慮到

紅色是取值的順序。

1.今天週一    天週一

 




0123
1123
2123
3213
4331

實現是去掉“今”,一步完成。

2.聽說馬上就要放假了 你聽說要放假了

 




01234567
11123456
22212345
33322345
44433345
55544445
66654555
77765456
88876546
99987664

這兩個字符串是:

去掉“你”,加上“馬上就”,總共四步操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章