我曾经为我的一个客户用 C 语言实现过这样的结构。最终结构是从描述字符集和 dawg 的 xml 文件加载的,另一个进程从单词列表创建 xml 文件。
第 1 步:构建第一个 dawg 序列化为 xml 文件的结构
我们用了 :
typedef struct _s_build_node build_node_t;
struct _s_build_node {
char_t letter;
build_node_t* first_child;
build_node_t* right_sibling;
hash_t hash;
size_t depth;
size_t ID;
};
typedef struct _s_build_dawg {
charset_t charset;
node_t* all_nodes; // an array of all the created nodes
node_t* root;
} build_dawg_t;
siblibgs 按升序排列,词尾特殊字符小于任何其他字符。该算法非常简单:
// create the build dawg
foreach word in wordlist
insert(dawg, word)
// compact the dawg
compact(dawg)
// generate the xml file
xml_dump(dawg)
为了压缩 dawg,我们为每个节点计算了一个哈希值。可以分解具有相同散列的两个节点。这部分可能很棘手。只有深度最低的节点被保留,其他节点被删除,它们的父节点现在指向保留的节点。
压缩后,我们为每个节点分配一个唯一的 ID(通过 bfs,ID 介于 0 和 N-1 之间,N 是压缩后的 dawg 中的节点数)。xml 文件简单地描述了 trie :
<dawg>
<charset ....>
...
</charset>
<node ID="node_id" letter="letter" fist_child="first_child_ID" next_sibling="next_sibling_id" />
<node .... />
<node .... />
<node .... />
</dawg>
第 2 步:最后的 dagw
结构稍微简单一点
typedef struct {
char_t letter;
size_t first_child;
size_t next_sibling;
} node_t;
typedef struct {
node_t nodes[];
... whatever you need ...
} dawg_t;
这里 root 是 dawg.nodes[0],first_child/next_sibling 是节点数组中的索引。从 xml 文件创建这样的结构很容易。主要缺点是任何词表修改都会触发新 xml 文件的生成。