SML - 使用延续在 trie 中收集单词

Posted

技术标签:

【中文标题】SML - 使用延续在 trie 中收集单词【英文标题】:SML - collecting words in a trie using continuations 【发布时间】:2012-03-15 18:35:55 【问题描述】:

我有一个 数据类型 trie = char 的节点 * (trie ref) 列表 |空的 我想收集trie中的所有单词,使用这两个相互递归的函数:

words_in_trie: trie -> (char list list -> 'a) -> 'a

all_words: trie ref list -> (char list list -> 'a) -> 'a

然后用 fun all_entries t = all_words t (fn l => map (fn w => String.implode w) l);

这必须通过延续来完成。我写成非续写形式,如下:

fun wt Empty = [[]] 
    |wt (Node(c,rl)) = map (fn (l) => c::l) (aw rl)
and aw [] = []
    |aw [h] = wt (!h)
    |aw (h::t) = (wt (!h))@(aw t)

但我不知道如何将它们转换为延续形式! 这是我到目前为止所拥有的,但它不起作用:

fun words_in_trie Empty cont = cont[] 
    |words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))
and all_words [h] cont = words_in_trie (!h) cont
    |all_words (h::t) cont = (words_in_trie (!h) cont)@(all_words t cont)

我多年来一直坚持这一点,我将不胜感激。

【问题讨论】:

标准 ML per se 没有延续。你是在使用Standard ML of New Jersey's SMLofNJ.Cont structure,还是其他地方的类似模块,还是自制的? 使用作为函数的延续 (char list list -> 'a),它将列表列表作为输入,表示到目前为止收集的单词的后缀 【参考方案1】:

由于延续的输入是单词的后缀,你知道在调用下一个延续之后,结果必须更接近于 trie 中的单词列表,并且仍然是单词的后缀。您可以使用它来确定延续应该做的是将下一个字母添加到 trie 之前(给定一个 char 列表列表,它将在列表中的每个 char 列表中添加一个 char)。

fun words_in_trie Empty cont = cont[]

如果您传递的 trie 是 Empty,那么您在该 trie 中有一个单词,这是一个空字符串。你想要的结果是[""]。回想一下,最后一个延续将列表中的每个 char list 转换为 string,因此为了获得该结果,您需要将一个带有空 char list 的列表传递给它以进行转换。

|words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))

回想一下:延续的类型是char list list -> 'ac 是一个char,所以它不能被添加到r,它是char list list 类型。

all_words 返回包含在尝试列表rl 中的所有单词的列表,您希望对其应用延续(将所有字符添加到 trie 前面)。您必须建立延续,以便除了将节点中的所有字符添加到特里之外,它还添加了当前节点的 char c。您正在寻找的是这样的:

fn x => cont (map (fn y => c::y) x)

上面的代码将c添加到列表中的每个char list,然后将其传递给下一个延续,继续添加下一个char

您的 all_words 函数对我来说看起来不错。

【讨论】:

all_words 的第二种情况也不是 CPS 形式。 我知道这是一个很晚的回复,但感谢您的回答!这是一个很大的帮助。

以上是关于SML - 使用延续在 trie 中收集单词的主要内容,如果未能解决你的问题,请参考以下文章

swift 在swift中收集单词的struct

hihocoder 1036 Trie图(AC自动机)

python 获取只收集一种单词的标签

试图在java中打印trie中的所有单词

常用电脑英语 200分收集

java 内容不重复的单词 set实现。