我有一个词汇,a
,abandon
,...,z
。
出于某种原因,我将使用数组而不是Trie来存储它们。
因此,一个简单的方法可以是:wordA\0wordB\0wordC\0...word\0
但我认为还有一些更经济的记忆方法。
由于like
是likely
的子字符串,我们只能存储like
的第一个位置和长度,而不是字符串本身。因此,我们生成一个“大字符串”,其中包含词汇表中的每个单词,并使用position[i]
和length[i]
来获取i
个单词。
例如,词汇表包含三个单词ab
,cd
和bc
。
我将abcd
构造为“大字符串”。
position[0] = 0, length[0] = 2
position[1] = 2, length[1] = 2
position[2] = 1, length[2] = 2
那么如何生成“大字符串”是这个问题的关键,有什么很酷的建议吗?
我认为问题类似于TSP问题(旅行商问题),这是一个NP问题。
答案 0 :(得分:0)
您正在寻找的搜索关键字是"字典"。即可用于存储单词列表的数据结构,并测试字典中是否存在其他字符串。
你的想法比分别存储每个单词更紧凑,但远不如DAWG这样的好数据结构紧凑。如您所知,如何最佳地选择如何重叠字符串并不明显。你正在做的事情有点像无损压缩方案(如gzip)那样做。如果您不需要针对紧凑字典检查单词,可能只需使用gzip或LZMA来压缩排序的单词列表。让他们的算法找到冗余并紧凑地表示它。
我查看词典,了解最近引起我兴趣的SO答案:Memory-constrained external sorting of strings, with duplicates combined&counted, on a critical server (billions of filenames)
对于不必动态添加新单词的字典,可以使用Directed Acyclic Word Graph。您可以通过跟随图形节点匹配字符串,直到您遇到没有边缘与下一个字符匹配的点,或者您到达输入字符串的末尾并发现DAWG中的节点被标记为是一个有效的词汇结尾。 (而不仅仅是一个只是某些单词前缀的子字符串)。有一些算法可以在合理的时间内从一个简单的单词数组字典构建这些状态机。
当整个单词是另一个单词的子串,或者一个单词的开头,另一个单词的开头时,你的方法只能利用冗余。 DAWG可以利用各处的常见子串,并且可以很快地匹配单词。可能与二进制搜索数据结构的速度相当,尤其是如果巨大的字符串太大而无法放入缓存中。 (一旦开始超出缓存大小,数据结构的紧凑性开始超过代码复杂性的速度。)
不太复杂但仍然有效的是Trie(或Radix Trie),其中公共前缀被合并,但后面的常见子字符串不会再次收敛。
如果您根本不需要修改DAWG或Trie,则可以将其有效地存储在单个内存块中,而不是动态分配每个节点。您没有说为什么您不想使用Trie,并且也没有承认其他数据结构的存在比平原更好地完成这项工作线索。