在树结构中链接

时间:2014-12-27 17:15:42

标签: haskell suffix-tree

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

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

有没有办法在Haskell中模拟这种行为?或者是否存在完全不同的替代方案?

1 个答案:

答案 0 :(得分:2)

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

以下计算构建一个值列表,每个值都包含列表中项目的总数,即使总计是由构建列表的相同函数计算的。 let中的zipCount绑定将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)]

这个想法可以通过传入未知的#来应用于Ukkonen's algorithm

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

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

我们可以在zipCountzipWithAndCount方面以无积分形式撰写fix

import Data.Function

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