【问题标题】:Linking in tree structures树结构中的链接
【发布时间】:2014-12-27 17:15:41
【问题描述】:

在使用长字符串时,我在 Haskell 中创建后缀树时遇到了一个相当大的问题。

一些构造算法(如 Ukkonen 算法的 this 版本)需要在节点之间建立链接。这些链接“指向”树中的一个节点。在 Java、C# 等命令式语言中,这不是问题,因为引用类型。

有没有办法在 Haskell 中模拟这种行为?还是有完全不同的选择?

【问题讨论】:

  • 当所有其他方法都失败时,您可以使用STSTRefs 编写有状态算法。然后你可以runST 得到你的纯后缀树。
  • 为什么 Ukkonen 的算法最近在 Haskell 标签中如此受欢迎,还有另一个问题,虽然没有正确的答案 - 只有 cmets 中的提示:stackoverflow.com/questions/19370296/…
  • 您只需要有向无环图吗?您可以使用 this 包中的图表。
  • 构建自引用结构的一个标准技巧称为“打结”。您可能会发现此问题的答案很有帮助:How do you represent a graph in Haskell?
  • 哦,还有一个unanswered question on a similar topic,里面有一些你可能会觉得有用的cmets。

标签: haskell suffix-tree


【解决方案1】:

您可以使用在tying a recursive knot 计算中的数据构造中的计算结果之前未确定的值。

以下计算会构建一个值列表,每个值都包含列表中的项目总数,即使总数是由构建列表的同一函数计算的。 zipCount 中的 let 绑定将zipWithAndCount 的一个结果作为第一个参数传递给zipWithAndCount

zipCount :: [a] -> [(a, Int)]
zipCount xs = 
    let (count, zipped) = zipWithAndCount count xs
    in zipped

zipWithAndCount :: Num n => b -> [a] -> (n, [(a, b)])
zipWithAndCount y [] = (0, [])
zipWithAndCount y (x:xs) =
    let (count', zipped') = zipWithAndCount y xs
    in (count' + 1, (x, y):zipped')

运行此示例会创建一个列表,其中每个项目都包含列表中总项目的计数

> zipCount ['a'..'e']
[('a',5),('b',5),('c',5),('d',5),('e',5)]

这个想法可以通过传入#s 应用于Ukkonen's algorithm,直到知道整个结果才知道。

将结果递归传递给函数的一般思想称为最小不动点,在Data.Function中由

实现
fix :: (a -> a) -> a
fix f = let x = f x in x

我们可以将zipCount 写成zipWithAndCountfix

import Data.Function

zipCount :: [a] -> [(a, Int)]
zipCount = snd . fix . (. fst) . flip zipWithAndCount

【讨论】:

    猜你喜欢
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多