【发布时间】:2012-09-26 09:06:23
【问题描述】:
我在这里找到了一个脚本,在查找最低公共子字符串时效果很好。
但是,我需要它来容忍一些不正确/缺失的字符。我希望能够输入所需的相似度百分比,或者指定允许的缺失/错误字符数。
比如我要查找这个字符串:
大黄色校车
这个字符串的内部:
那天下午他们乘坐的是大黄校车
这是我目前使用的代码:
function longest_common_substring($words) {
$words = array_map('strtolower', array_map('trim', $words));
$sort_by_strlen = create_function('$a, $b', 'if (strlen($a) == strlen($b)) { return strcmp($a, $b); } return (strlen($a) < strlen($b)) ? -1 : 1;');
usort($words, $sort_by_strlen);
// We have to assume that each string has something in common with the first
// string (post sort), we just need to figure out what the longest common
// string is. If any string DOES NOT have something in common with the first
// string, return false.
$longest_common_substring = array();
$shortest_string = str_split(array_shift($words));
while (sizeof($shortest_string)) {
array_unshift($longest_common_substring, '');
foreach ($shortest_string as $ci => $char) {
foreach ($words as $wi => $word) {
if (!strstr($word, $longest_common_substring[0] . $char)) {
// No match
break 2;
}
}
// we found the current char in each word, so add it to the first longest_common_substring element,
// then start checking again using the next char as well
$longest_common_substring[0].= $char;
}
// We've finished looping through the entire shortest_string.
// Remove the first char and start all over. Do this until there are no more
// chars to search on.
array_shift($shortest_string);
}
// If we made it here then we've run through everything
usort($longest_common_substring, $sort_by_strlen);
return array_pop($longest_common_substring);
}
非常感谢任何帮助。
更新
PHP levenshtein 函数限制为 255 个字符,而我正在搜索的一些 haystacks 是 1000+ 个字符。
【问题讨论】:
-
我想说您应该使用自定义字符串比较函数,该函数将使用一个符号容差。算法可能是这样的:一次将两个符号与最长的公共子字符串进行比较,一旦找到其中一个,就可以逐个符号进行比较。如果不匹配,检查容差阈值,如果失败,继续搜索 LCS 的可能开始。如果成功,添加容差并检查下一个符号,将它们相互比较,并首先比较未处理的 LCS 符号。如果成功,继续检查,就像刚刚发现遗漏或错误一样。
-
Wagner-Fischer 可能会给您一个很好的起点。您也许可以查看矩阵上生成的对角线并在此基础上解决问题。 en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm我也会考虑的。
标签: php string-matching levenshtein-distance longest-substring