+-- This module solves, more or less, the maximal unique match (MUM)

+-- problem for two input lists, using a generalised suffix tree.

+-- Unfortunately, we can't check for left maximality because we're

+-- using lists instead of indices into arrays. It's easy to look one

+-- element to the left in an array, but you can't look one element

+-- left of the head of a list.

+module UniqueMatch (Sym(..), mkGenTree, maxUniqueMatches) where

+import Data.SuffixTree (STree(..), construct, prefix)

+-- We construct a generalised suffix tree, with elements annotated to

+-- tell us whether they come from the left or right list. Each list

+-- is terminated with a stop symbol.

+fromSyms (L a:ss) = a : fromSyms ss

+fromSyms (R a:ss) = a : fromSyms ss

+instance (Eq a) => Eq (Sym a) where

+instance (Ord a) => Ord (Sym a) where

+mkGenTree :: (Ord a) => [a] -> [a] -> STree (Sym a)

+mkGenTree a b = construct (map L a ++ Lx : map R b ++ [Rx])

+maxUniqueMatches :: (Ord a) => STree (Sym a) -> [[a]]

+maxUniqueMatches t = map (fromSyms . concatMap prefix . reverse)

+ where recurse _ Leaf = []

+ recurse path (Node es) = loop path es

+ loop path ((p, t):es) = matches ++ loop path es

+ where matches | rightMaximal t = [p:path]

+ | otherwise = recurse (p:path) t

+ rightMaximal (Node [(pa,Leaf), (pb,Leaf)]) =

+ (isLeft a && isRight b) || (isRight a && isLeft b)