用几种语言保存整个句子的数据结构

时间:2015-08-08 19:42:34

标签: data-structures

我计划用某种语言保存大量的句子,以便每个元素都有一个指向该句子翻译成不同语言的指针。
通过对句子进行排序,我可以创建一个平衡二叉树,并在O(logn)中添加/删除/搜索 有没有办法将元素保存在哈希表中?在这种情况下哈希函数会是什么样子? 我希望能够用任何语言搜索一个句子并以任何其他语言返回它的翻译 如果我有K语言,使用平衡树我得到k树的O(klogn)搜索时间 还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

是的,trie更适合字符串搜索。此外,我将所有语言的所有句子存储在单个trie中,其中value是所有可用翻译的列表。

在这种情况下的搜索将是O(k),其中k是搜索句子的长度。

<强> UPD 如果您只搜索已知语言并翻译成另一种已知的语言,那么:

将每个值设为Map<(Source Language) → Map<(Target language) → Translation>>

您将拥有以下工作流程:查找与trie中给定句子相对应的值。在找到的源搜索地图语言中。如果找到,这意味着句子是目标语言(假设语言之间可能存在冲突)。此时发现Map(内部)代表目标语言的所有可用翻译。搜索所需的一个。

实现两个Maps的最高性效的方法是普通数组。其中i-th元素表示i-th转换的值(假设您具有有限数量的转换,并且您可以为每个转换分配不同的索引)。搜索已知的转换将是O(1) - 只是访问数组中的已知索引。但是这种方法也会消耗大量内存,就好像你在Map中有稀疏值一样,你的后备数组仍会消耗固定数量的内存(与所有可能的翻译数量成比例)。

但是这种方法适用于内部地图(据我所知,存储了所有可能语言的翻译)。

对于我可以期望稀疏的外部地图,您有以下几种选择:

  • 如果不同语言的句子之间的平均碰撞次数很少(1-2),您只需在列表中存储Key→Value对。平均搜索时间将保持不变。
  • 如果平均碰撞次数很多,但仍然不足以与数组一起使用(内部地图的方法),那么通过Hashtable支持这个Map,其大小将是Map中预期的值数 - 平均碰撞次数。然后你将再次分摊O(1)搜索时间。
  • 地图似乎很密集 - 使用数组方法,如内部地图。

UPD2 示例:

假设您有下一个相互翻译的句子: 你好[en] Hola [西班牙文] 你好[nl] 你好[de]

您应将所有这些内容添加到trie中,并使用以下值:

Hello -> Map([en] -> Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo))
Hola -> Map([es] -> Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo))
Hallo -> Map([nl] -> Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo),
             [de] -> Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo))

此处的方括号与数组无关,它们用于在视觉上区分语言。

所以,当你在trie中进行搜索时,你不知道你的句子是哪种语言。当您从特里(地图图)中获取值时,您可以将句子的原始语言“映射”为所需语言的翻译。

回到例子,如果你有句号“Hallo”并且你知道它在[de]中,你想将它翻译成[en]。 你在特里搜索“你好”,然后得到:

Map([nl] -> Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo),
             [de] -> Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo))

现在你可以从这张地图中获得[de]的价值(正如你在[de]中所说的那样)。你会得到:

Map([en]->Hello, [es]->Hola, [nl]->Hallo, [de]->Hallo)

现在在此地图中搜索目标语言([en])。你会得到“你好”。

当然,不是Trie-&gt; Map-&gt; Map结构,您可以使用Map-&gt; Trie-&gt; Map,其中第一个Map将源语言映射到相应的词典,由trie表示。但我认为这样的内存效率较低,因为看起来不同语言中的单词通常共享相同的前缀,因此将它们放在单个trie中会保留内存。但在性能效率方面却是一样的,所以这取决于你。