關於文字糾錯之編輯距離
技術標籤:NLP編輯距離文字相似MySQL演算法Levenshtein
一 編輯距離
目的糾錯。以下為百科介紹
Levenshtein 距離,又稱編輯距離,指的是兩個字串之間,由一個轉換成另一個所需的最少編輯操作次數。
許可的編輯操作包括將一個字元替換成另一個字元,插入一個字元,刪除一個字元。
編輯距離的演算法是首先由俄國科學家Levenshtein提出的,故又叫Levenshtein Distance。
演算法也是比較經典的,https://leetcode-cn.com/problems/edit-distance/
還是動態規劃實現。
理論部分到此結束
二落地
如果MYSQL資料量少,可以使用自定義的函式。程式碼如下:
DELIMITER $$ CREATE FUNCTION levenshtein( s1 VARCHAR(255), s2 VARCHAR(255) ) RETURNS INT DETERMINISTIC BEGIN DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; DECLARE s1_char CHAR; -- max strlen=255 DECLARE cv0, cv1 VARBINARY(256); SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0; IF s1 = s2 THEN RETURN 0; ELSEIF s1_len = 0 THEN RETURN s2_len; ELSEIF s2_len = 0 THEN RETURN s1_len; ELSE WHILE j <= s2_len DO SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1; END WHILE; WHILE i <= s1_len DO SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1; WHILE j <= s2_len DO SET c = c + 1; IF s1_char = SUBSTRING(s2, j, 1) THEN SET cost = 0; ELSE SET cost = 1; END IF; SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost; IF c > c_temp THEN SET c = c_temp; END IF; SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1; IF c > c_temp THEN SET c = c_temp; END IF; SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1; END WHILE; SET cv1 = cv0, i = i + 1; END WHILE; END IF; RETURN c; END$$ DELIMITER ;
使用語法:SELECT * from test where levenshtein('品他病損害',name) BETWEEN 0 AND 3
可見這種模糊查詢的效果是like實現不了的。
但是能否線上落地,需要自己評估數量。因為畢竟是自定義函式。資料量少幾百條几千條OK,要是幾萬條得驗證下,很可能就是一個SQL10秒了。
我不推薦這種方式。資料庫掛了就因小失大了。
自己寫OK。也可以偷懶找個三方的庫。
推薦用apache的
這裡的quer就是查詢的,target就是字典的。假設無序的前提下暴力迴圈就好
int sdistance = LevenshteinDistance.getDefaultInstance().apply(query, target);
具體distance的範圍,需要根據業務去做取捨。如果》3我覺得就偏差太多,難以起到糾錯的目的。
我們以醫院為例:假設目標有
首都兒科研究所
北京佑安醫院
String query = "首度兒科研究所"; System.out.println(EditDistanceUtil.match(query, str));
就能找到:首都兒科研究所
三 HammingDistance
漢明距離,提一下也不展開。在包括資訊理論、編碼理論、密碼學等領域都有應用。我理解是偏2個二進位制碼字之間的相似程度的。
我目前的感覺是,編輯距離是硬匹配。怎麼解釋下呢?就是沒有業界那種考慮上下文的好。
***************************
看到這裡了,如果對你有所幫助,就點個贊吧。