2

我的朋友在一次采访中遇到了这个问题。我们得到一个包含一些句子的文件。句子只有 0-9, az, AZ 和句号(.) ,我们需要读取文件并以查询更快的方式存储。这个阶段所花费的时间不是问题。这里查询将包含一些单词,我们需要返回包含所有这些单词的最小子字符串。顺序并不重要。(注意:假设整个文件可以放在主存中)

例如,如果文件是:“Ram 正在攻读计算机科学学位。Ram 家里有电脑。Ram 现在在家。”

查询 1:"Ram computer a" 输出:"Ram has a computer" 查询 2:"Ram home" 响应:"home.Ram"

我想将文件存储为一个链接列表,其中每个节点都由一个单词组成。如果是最后一个单词,则单词+句号存储在节点中。在查询时,我们需要遍历 LL 并找到包含所有单词的最小字符串。

我们如何进一步优化它?我们可以以更好的方式存储文件吗?

4

1 回答 1

2

您可以将文件以Suffix array的形式存储。它可以在 O(N) 时间内构建,其中 N 是文件的长度。每个查询词可以在 O(M + log N) 时间内通过二分查找找到,其中 M 是查询词的长度。如本文所示:Mohamed Ibrahim Abouelhodaa、Stefan Kurtzb、Enno Ohlebusch 的“用增强的后缀数组替换后缀树”,我们可以将其改进为 O(M)。

由于预处理阶段所花费的时间不是问题,因此您可以使用Trie代替后缀数组。只需将输入文件的每个单词添加到 trie 中,并将文件中该单词的位置添加到该单词的位置列表中(每个 trie 节点都需要一个这样的列表)。

在后缀数组或trie中找到所有查询词的位置后,您必须对它们进行排序(仅针对后缀数组,因为它们在trie的情况下已经排序),然后找到一组最接近的位置其他:

  1. 将所有查询词的最小位置添加到优先队列(可以实现为最小堆),
  2. 虽然此优先级队列中顶部单词的尚未处理位置列表不为空,但将顶部队列条目替换为同一单词的下一个位置。每次从优先级队列中添加/删除某个条目时,将相应单词末尾的位置添加/删除到某个有序集合(如二叉搜索树)。该集合中的最大条目与优先级队列中的最小条目之间的差异允许确定具有所有查询词的最小子串。
于 2013-04-20T13:42:46.817 回答