使用词典查找可能是原始字符串的所有可能单词的列表

时间:2016-05-27 16:01:41

标签: string algorithm data-structures

我的朋友在他的一次采访中提到了这个问题。虽然他不会逐字记住这个问题,但他能够尽可能地回忆下方的情况。

从发送方向接收方发送字符串(一个字)。在传输过程中,字符串的一个字母被更改。使用词典查找可能是原始字符串的所有可能单词的列表。您不知道原始字符串是什么,您只能访问您收到的字符串和字典。

第一次看到这个问题时,我想到的第一件事就是迭代地替换字符串中的所有字符,然后将它们与字典中的单词进行比较。如果有匹配,那么我会将该单词存储在一个数组中。(假设不区分大小写)

例如:

原文:猫

收到的字:蝙蝠

我的算法:

遍历字典并将OriginalWord.length()的所有单词放入HashTable

[a-z] .....检查这些是否在hashTable中

b [a-z] t ....检查其中任何一个是否在hashTable中

ba [a-z] ....检查其中任何一个是否在hashTable中

我的朋友说这是他使用的算法,但采访者说没有优化。我一直在研究这个问题,虽然我发现没有完全喜欢它。我找到了一些参考Levenshtein距离。我对高级算法的了解有限,所以我无法理解它。此外,由于我无法访问访调员,因此我无法回复具体内容(例如,允许对字典进行预处理,在某些情况下会发生什么情况等等)。尽可能地解释问题并做出合理的假设。

假设允许预处理字典。在这样的场景中询问面试官有什么问题,以及可以用来解决这个问题的更好/更优化的算法是什么?

2 个答案:

答案 0 :(得分:3)

如果您允许通过创建automaton来预处理字典,则可以在线性时间内解决。

首先创建一个自动机,决定字符串是否在字典中。 Aho Corasick是创建此类自动机的算法的一个示例。 trie也基本上做同样的事情(尽管效率较低)

复制此自动机,您现在有两个自动机,Q1,Q2。起始状态在Q1,结束状态在Q2。通过在Q1中的每个状态添加一个非确定性步骤来连接自动机,到Q2中的下一个状态,但具有不同的字符。

例如,如果您有州:

A---a-->B

添加:

A--b-->B'. A--c-->B', ...., A--z-->B'

其中A,B是Q1中的状态,B'是等于B的州 - 但是在第二季度。

这允许你通过转到Q2来忽略一个错误(然后你不能再忽略任何错误)。

自动机创建完成后(并处理回确定性自动机),在查询时间,您将获得线性时间的匹配。

答案 1 :(得分:2)

你可以通过从字典创建一个trie来做到这一点。但不是以正常方式搜索,而是进行通配符搜索。使用您的示例,给定字符串“bat”,您搜索“* at”。因此,对于trie中的每个顶级节点,您需要查找以“at”结尾的3个字母的单词。

然后你搜索“b * t”。也就是说,你转到顶级节点'b',对于'b'后面的每个字符,搜索't'作为下一个字母。

最后,你搜索“ba *”。也就是说,对于前缀“ba”,您要查找下一个字符为“t”。

假设字母a-z,其最大复杂度为26 * n,其中n是单词中的字符数。实际上它可能会少得多,因为并非所有角色都会在所有级别上。例如,您将找不到以“bz”或“bq”开头的英语单词。

这会奏效,但我似乎记得你可以用suffix tree更有效率地做到这一点。