【发布时间】:2017-05-11 00:38:51
【问题描述】:
我正在使用以下数据类型:
data SuffixTree = Leaf Int | Node [(String, SuffixTree)]
deriving (Eq, Show)
每个子树都有一个对应的标签(字符串)。
想法是通过将每个后缀及其索引添加到累积树中来构建相应的后缀树(开头是Node [])。
这已经定义了
buildTree s
= foldl (flip insert) (Node []) (zip (suffixes s) [0..length s-1])
suffixes 的定义正确。
我一直在尝试实现insert 函数一段时间,但似乎无法成功。
这是我现在拥有的(名称和样式不是最好的,因为这仍在进行中):
insert :: (String, Int) -> SuffixTree -> SuffixTree
insert pair tree@(Node content)
= insert' pair tree content
where
insert' :: (String, Int) -> SuffixTree -> [(String, SuffixTree)] -> SuffixTree
insert' (s, n) (Node []) subtrees
= Node ((s, Leaf n) : subtrees)
insert' (s, n) (Node content@((a, tree) : pairs)) subtrees
| null p = insert' (s, n) (Node pairs) subtrees
| p == a = insert' (r, n) tree subtrees
| p /= a = Node ((p, newNode) : (subtrees \\ [(a, tree)]))
where
(p, r, r') = partition s a
newNode = Node [(r, (Leaf n)), (r', tree)]
partition 函数接受两个字符串并返回一个包含以下内容的元组:
- 通用前缀(如果存在)
- 第一个不带前缀的字符串
- 不带前缀的第二个字符串
我想我了解构建树所需的规则。
我们首先将第一个子树的标签与我们要插入的字符串(例如,str)进行比较。如果它们没有共同的前缀,我们会尝试在下一个子树中插入。
如果标签是str 的前缀,我们会继续查看该子树,但我们不使用str,而是尝试插入不带前缀的str。
如果str 是标签的前缀,那么我们将现有的子树替换为新的Node,具有Leaf 和旧的子树。我们还调整了标签。
如果我们在str 和任何标签之间没有匹配,那么我们将一个新的Leaf 添加到子树列表中。
但是,我遇到的最大问题是我需要返回包含更改的新树,因此我必须跟踪树中的其他所有内容(不知道如何执行此操作,或者我的想法是否正确关于这个)。
代码似乎在此字符串上正常工作:"banana":
Node [("a",Node [("",Leaf 5),("na",Node [("",Leaf 3),("na",Leaf 1)])]),
("na",Node [("",Leaf 4),("na",Leaf 2)]),("banana",Leaf 0)]
但是,在这个字符串 "mississippi" 上,我得到一个 Exception: Non-exhaustive patterns in function insert'。
非常感谢任何帮助或想法!
【问题讨论】:
-
您的基本情况是问题所在 - 我敢打赌
insert'在某些时候会被Leaf调用(仅基于错误消息和您的数据类型)。 -
我也一直在考虑这个问题。但是,在尝试了一些变化之后,我仍然没有弄清楚。
-
你可能想改用
Node [(Char, SuffixTree)],我预感它会大大简化逻辑。
标签: string haskell recursion tree suffix-tree