【问题标题】:Look for a data structure to match words by letters寻找按字母匹配单词的数据结构
【发布时间】:2020-04-02 15:45:46
【问题描述】:

给定一个小写随机单词列表,每个单词的长度相同,并且指定了许多模式,每个模式在某些位置有一些字母,而其他字母是未知的,找出与每个模式匹配的所有单词。

例如,单词列表是:

["ixlwnb","ivknmt","vvqnbl","qvhntl"]

模式是:

i-----
-v---l
-v-n-l

使用简单算法,可以为每个模式进行 O(NL) 次旅行,其中 N 是字数,L 是字长。

但是由于可能有很多模式在同一个单词列表上传播,是否有任何好的数据结构来预处理和存储单词列表,然后为所有模式提供足够的匹配?

【问题讨论】:

    标签: algorithm data-structures


    【解决方案1】:

    一个简单的想法是使用倒排索引。首先,为你的单词编号——你将使用这些索引而不是单词本身来引用它们,以提高速度和空间效率。索引可能适合 32 位 int。

    现在您的倒排索引:对于每个位置的每个字母,为在该位置具有该字母的单词构建一个排序的 ID 列表。

    要进行搜索,您需要获取给定位置中每个字母的 ID 列表,然后使用类似于合并排序中的“合并”的算法获取列表的交集。交集中的所有 ID 都与输入匹配。

    或者,如果您的单词足够短(12 个字符或更少),您可以将它们压缩为 64 位单词(每个字母使用 5 位,字母 1-26)。在有字母的地方用二进制11111 构造一个位掩码,在有空格的地方用00000 构造一个位掩码。并使用00000 对每个位置的每个字母使用 5 位代码对您的输入进行位测试,其中您有空格。例如,如果您的输入是a-c,那么您的位掩码将是二进制111110000011111,而您的bittest 二进制是000010000000011。浏览您的单词列表,使用位掩码获取每个单词的按位and 并测试它是否等于位测试值。这是缓存友好的,并且内部循环很紧凑,因此可能与看起来应该更快的算法竞争。

    【讨论】:

    • 不错的解决方案,对 ID 排序列表的合并想法和压缩单词到位测试想法很棒。
    【解决方案2】:

    我会以更多的评论和更少的答案作为开头(虽然我没有足够的声誉来评论)。我想不出任何能够满足盒子要求的数据结构。想想很有趣,我想我会分享一个突然出现在我脑海中的潜在解决方案。

    我输入了“相同长度”部分,并认为我可以根据它想出一些东西。

    理论上我们可以有 N(N 是长度) char -> 集合的映射。 添加字符串时,它会遍历每个字符并将字符串添加到相应的集合中。伪代码:

    firstCharMap[s[0]].insert(s);
    secondCharMap[s[1]].insert(s);
    thirdCharMap[s[2]].insert(s);
    fourthCharMap[s[3]].insert(s);
    fifthCharMap[s[4]].insert(s);
    sixthCharMap[s[5]].insert(s);
    

    然后要确定哪些字符串与模式匹配,我们只需做集合的交集 ex:“-v-n-l”将是: 集合的交集:secondCharMap[v]、fourthCharMap[n]、sixthCharMap[l]

    跳出的一个极端情况是,如果我只想获取所有字符串,那么如果这是一个要求 - 我们可能还需要一组额外的所有字符串。

    这个解决方案感觉很笨拙,但我认为它可以工作。取决于语言、字符串的数量等——如果它的性能比仅遍历所有字符串并检查谓词更差,我不会感到惊讶。

    【讨论】:

    • 仍然想知道交叉部分是否有任何改进。我曾尝试应用分段树数据结构,但未能解决。
    • 是的,我的第一个想法是必须有一种方法来处理树木。我想知道您是否可以将所有字符串存储在一棵树中,树的每一层都有每个字符的节点。然后查找所有字符串将根据您的查询编写访问者。 “-v-n-l”将:访问第一级的所有节点,仅访问第二级的 v 节点,访问第三级的所有节点,等等。我不确定它的效果如何,我不记得最后一个我真的发现需要编写自己的树而不是使用 stl 容器。
    • @JosephDing 如果您想一次性匹配,如果字符串长度很短,请将所有可能的子序列存储在映射中。
    猜你喜欢
    • 2018-08-30
    • 2015-08-22
    • 2017-10-09
    • 2013-08-25
    • 2010-12-29
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 2017-03-02
    相关资源
    最近更新 更多