我正在Go中实现简约非循环有限状态自动机(MA-FSA;一种特定类型的DAG),并希望将一些额外数据与指示EOW(字尾)的节点相关联。使用MA-FSA,传统方法是不可能的,因为有多个单词可能在该节点结束。所以我正在寻找最小的完美散列函数作为替代。
在his blog post, Steve Hanov顶部的“更正”框中,他说他使用了this paper by Lucchesi and Kowaltowski中描述的方法。在查看图12 (第19页)时,它描述了散列函数。
在第8行,它引用FirstLetter
和Predecessor()
,但它没有描述它们是什么。或者我没有看到它。它们是什么?
我只能弄清楚它只是遍历树,在每个节点上加上Number
,但这可能不对。它产生的数字太大而且不是一对一的,就像论文所说的那样。我误读了什么吗?
答案 0 :(得分:1)
报纸说:
让我们假设我们的自动机的表示包括,对于每个状态,一个整数,它给出自动机从该状态开始接受的单词数。
所以我相信这一点:for C <- FirstLetter to Predecessor(Word[I ]) do
意味着:for (c = 'a'; c < word[i]; c++)
(他们只是试图独立于字母表。)
这样想:枚举所有被接受的词。排序他们。在列表中找到您的单词。它的索引是单词的哈希值。
他们的算法通过跟踪从给定节点可以访问的单词数来避免存储完整列表。因此,您到达一个节点,并在下一个字母之前检查所有涉及字母表字母的其他节点的传出边缘。从这些节点可以访问的所有单词必须在单词之前的列表中,这样您就可以计算单词在列表中必须占据的位置。
答案 1 :(得分:1)
我更新了我的DAWG示例,将其显示为从键到值的映射。每个节点存储可从其访问的最终节点的数量(包括其自身)。然后当遍历trie时,我们将我们跳过的任何计数加起来。这样,特里结构中的每个单词都有一个唯一的数字。然后,您可以在数组中查找数字,以获取与单词相关联的数据。