And*_*ark 44 mysql database algorithm search levenshtein-distance
我希望能够按照以下方式搜索一个表格,因为它可以获得1个方差范围内的所有内容.
数据:
O'Brien Smithe Dolan Smuth Wong Smoth Gunther Smiht
我已经研究过使用Levenshtein距离有没有人知道如何实现它?
有一个Levenshtein距离函数的mysql UDF实现
https://github.com/jmcejuela/Levenshtein-MySQL-UDF
它在C中实现,并且具有比schnaader提到的"MySQL Levenshtein距离查询"更好的性能
小智 5
damerau-levenshtein距离的实现可以在这里找到: Damerau-Levenshtein算法:具有转置 的Levenshtein对纯Levenshtein距离的改进是考虑字符的交换.我在schnaader链接的评论中找到了它,谢谢!
上面为 levenshtein <= 1 给出的函数是不正确的——它给出了不正确的结果,例如“床”和“出价”。
我修改了上面给出的“MySQL Levenshtein 距离查询”,在第一个答案中,接受一个“限制”,这会稍微加快速度。基本上,如果您只关心 Levenshtein <= 1,请将限制设置为“2”,如果为 0 或 1,该函数将返回精确的 Levenshtein 距离;或 2 如果精确的 levenshtein 距离为 2 或更大。
这个 mod 让它快 15% 到 50%——你的搜索词越长,优势就越大(因为算法可以提前保释。)例如,在针对 200,000 个词的搜索中找到距离 1 的词的所有匹配项“咯咯笑”,原始版本在我的笔记本电脑上需要 3 分 47 秒,而“限制”版本则为 1:39。当然,这些对于任何实时使用来说都太慢了。
代码:
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$$
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
40129 次 |
最近记录: |