Chức năng được cung cấp cho levenshtein < = 1 ở trên không đúng - nó cho kết quả không chính xác ví dụ: "giường" và "giá thầu".
Tôi đã sửa đổi "truy vấn khoảng cách Levenshtein MySQL" đã nêu ở trên, trong câu trả lời đầu tiên, để chấp nhận "giới hạn" sẽ tăng tốc độ một chút. Về cơ bản, nếu bạn chỉ quan tâm đến Levenshtein < = 1, đặt giới hạn thành "2" và hàm sẽ trả về khoảng cách levenshtein chính xác nếu nó là 0 hoặc 1; hoặc 2 nếu khoảng cách levenshtein chính xác là 2 hoặc cao hơn.
Mod này giúp từ 15% đến 50% nhanh hơn - từ tìm kiếm càng dài, lợi thế càng lớn (vì thuật toán có thể bảo lãnh trước đó). Ví dụ: tìm kiếm 200.000 từ để tìm tất cả các kết quả phù hợp trong khoảng cách 1 của từ "cười khúc khích", bản gốc mất 3 phút 47 giây trên máy tính xách tay của tôi, so với 1:39 cho phiên bản "giới hạn". Tất nhiên, đây là cả hai quá chậm cho bất kỳ sử dụng thời gian thực.
Code:
DELIMITER $$
CREATE FUNCTION levenshtein_limit_n(s1 VARCHAR(255), s2 VARCHAR(255), n INT)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost, c_min 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, c_min = 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 and c_min < n DO -- if actual levenshtein dist >= limit, don't bother computing it
SET s1_char = SUBSTRING(s1, i, 1), c = i, c_min = 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;
IF c < c_min THEN
SET c_min = c;
END IF;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
IF i <= s1_len THEN -- we didn't finish, limit exceeded
SET c = c_min; -- actual distance is >= c_min (i.e., the smallest value in the last computed row of the matrix)
END IF;
RETURN c;
END$$
+1 - Tôi đã thực hiện điều này một, tôi nhìn vào nó trước khi đăng. Các công trình của nó nhưng việc đặt nó vào một tìm kiếm (với một số hiệu suất) là những gì tôi đang cố gắng tìm ra. –
Liên kết dường như không còn nữa. Đây là một http://www.artfulsoftware.com/infotree/queries.php#552 –
điều này không hoạt động cho các ký tự utfmb4 và cung cấp lỗi – akabhirav