我的朋友在他的一次采访中提到了这个问题。虽然他不会逐字记住这个问题,但他能够尽可能地回忆下方的情况。
从发送方向接收方发送字符串(一个字)。在传输过程中,字符串的一个字母被更改。使用词典查找可能是原始字符串的所有可能单词的列表。您不知道原始字符串是什么,您只能访问您收到的字符串和字典。
第一次看到这个问题时,我想到的第一件事就是迭代地替换字符串中的所有字符,然后将它们与字典中的单词进行比较。如果有匹配,那么我会将该单词存储在一个数组中。(假设不区分大小写)
例如:
原文:猫
收到的字:蝙蝠
我的算法:
遍历字典并将OriginalWord.length()的所有单词放入HashTable
[a-z] .....检查这些是否在hashTable中
b [a-z] t ....检查其中任何一个是否在hashTable中
ba [a-z] ....检查其中任何一个是否在hashTable中
我的朋友说这是他使用的算法,但采访者说没有优化。我一直在研究这个问题,虽然我发现没有完全喜欢它。我找到了一些参考Levenshtein距离。我对高级算法的了解有限,所以我无法理解它。此外,由于我无法访问访调员,因此我无法回复具体内容(例如,允许对字典进行预处理,在某些情况下会发生什么情况等等)。尽可能地解释问题并做出合理的假设。
假设允许预处理字典。在这样的场景中询问面试官有什么问题,以及可以用来解决这个问题的更好/更优化的算法是什么?
答案 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更有效率地做到这一点。