【问题标题】:Check if one string includes a substring with Levenshtein distance of 1 from other string检查一个字符串是否包含与其他字符串的 Levenshtein 距离为 1 的子字符串
【发布时间】:2017-12-05 13:07:25
【问题描述】:

我的问题是我们希望我们的用户输入这样的代码: 639195-EM-66-XA-53-WX 在输入中的某处,因此结果可能如下所示:The code is 639195-EM-66-XA-53-WX, let me in。如果它们在代码中出现小错误(Levenshtein 距离为 1),我们仍然希望匹配字符串。例如The code is 739195-EM-66-XA-53-WX, let me in。 (代码首字母6改成7)

即使用户跳过破折号,算法也应该匹配,并且它应该忽略小写/大写字母。这些要求很容易满足,因为我可以删除所有破折号并执行 to_uppercase。

有类似的算法吗?

生成与原始代码距离为 1 的所有字符串的计算成本很高。

我也在考虑使用 Levenshtein distance 之类的东西,但忽略用户在第二个字符串中添加的缺失字母,但这会导致代码中间出现错误的字母。

在用户输入中搜索代码似乎好一点,但仍然不是很干净。

【问题讨论】:

  • 那么你知道代码前后的字母或单词,即输入代码之前的句子吗?两个字符串之间的最大 Levenshtein 距离为 1 很容易高效地实现 O(n)。
  • 不,我不知道前后的字母。我会在问题中说清楚。

标签: algorithm string-matching levenshtein-distance


【解决方案1】:

我有一个解决方案的想法,也许这对你来说已经足够了:

如您所说,首先删除破折号并将所有内容设为大写(或小写):

句子:THE CODE IS 639195EM66XA53WX, LET ME IN

代码:639195EM66XA53WX

把中间的代码分开(c1和c2),因为Levenshtein距离为1意味着只能出现一个错误(插入、删除或替换单个字符),所以c1或c2中的一个要匹配if代码出现在句子中,只有 1 个或更少的错误。在中间拆分,因为代码的两个子字符串越长,您应该获得的匹配项就越少:

c1:639195EM

c2:66XA53WX

现在尝试在句子中查找 c1 和 c2,如果找到匹配项,则必须在句子中向前(匹配 c1)或向后(匹配 c2)检查缺失部分的 Levenshtein 距离是否为1 个或更少。

所以在你的例子中你会找到 c2 然后:

  1. 将指针设置为 c1 的最后一个字符和匹配前的字符。
  2. 虽然字符相同,但将两个指针都减 1(在两个字符串中倒退)。
  3. 如果您可以通过这种方式完全消耗 c1,您会发现完全匹配(Levenshtein 距离为 0)。

  4. 否则尝试 Levenshtein 距离为 1 的 3 种可能性:

    1. 只将c1的指针向后移动,看​​其余是否匹配(删除)。

    2. 只将句子的指针向后移动,看​​其余是否匹配(插入)。

    3. 向后移动两个指针,看看其余的是否匹配(替换)。

  5. 如果其中一个成功,则您找到了 Levenshtein 距离为 1 的匹配项,否则距离更大。

【讨论】:

  • 拆分是一个令人信服的想法,因为它允许我在用户输入中找到正确的位置。我想知道是否可以直接在代码的第二部分使用 Levenshtein 距离(使用开箱即用的解决方案),但它不适用于插入。看起来这个算法非常适合我的情况!
猜你喜欢
  • 2018-08-27
  • 2019-01-04
  • 2011-11-09
  • 2013-05-18
  • 1970-01-01
  • 2017-05-12
  • 2019-08-06
  • 2014-06-25
  • 2021-12-20
相关资源
最近更新 更多