module Data.List.Kmp.Internal
(
KmpState(..),
GenericKmpState(..),
kmpTraverse,
kmpTraverseBy,
gKmpTraverse,
gKmpTraverseBy
)
where
import Data.Maybe
data KmpState a = KmpState { kmpTail :: [a], kmpLength :: !Int, kmpPrev :: [KmpState a] }
kmpTraverse :: Eq a => [a] -> [KmpState a]
kmpTraverse [] = []
kmpTraverse xw@(_:xs) = let
pk = KmpState{kmpTail = xw, kmpLength = 0, kmpPrev = pks}
k = KmpState{kmpTail = xs, kmpLength = 0, kmpPrev = pks}
pks = pk:ks
ks = k:go k xs
in ks
where
go _ [] = []
go pk (x:xs) = let k = recurse pk x xs
in k:go k xs
recurse KmpState{kmpLength = kl, kmpPrev = kpw@(kp@KmpState{kmpTail = kpt:_}:kps)} x xs
| kpt == x = KmpState{kmpTail = xs, kmpLength = kl + 1, kmpPrev = kps}
| kl == 0 = KmpState{kmpTail = xs, kmpLength = 0, kmpPrev = kpw}
| otherwise = recurse kp x xs
kmpTraverseBy :: (a -> a -> Bool) -> [a] -> [KmpState a]
kmpTraverseBy eq [] = []
kmpTraverseBy eq xw@(_:xs) = let
pk = KmpState{kmpTail = xw, kmpLength = 0, kmpPrev = pks}
k = KmpState{kmpTail = xs, kmpLength = 0, kmpPrev = pks}
pks = pk:ks
ks = k:go eq k xs
in ks
where
go _ _ [] = []
go eq pk (x:xs) = let k = recurse eq pk x xs
in k:go eq k xs
recurse eq KmpState{kmpLength = kl, kmpPrev = kpw@(kp@KmpState{kmpTail = kpt:_}:kps)} x xs
| kpt `eq` x = KmpState{kmpTail = xs, kmpLength = kl + 1, kmpPrev = kps}
| kl == 0 = KmpState{kmpTail = xs, kmpLength = 0, kmpPrev = kpw}
| otherwise = recurse eq kp x xs
data GenericKmpState i a = GenericKmpState { gKmpTail :: [a], gKmpLength :: Maybe i, gKmpPrev :: [GenericKmpState i a] }
gKmpTraverse :: (Num i, Eq a) => [a] -> [GenericKmpState i a]
gKmpTraverse [] = []
gKmpTraverse xw@(_:xs) = let
pk = GenericKmpState{gKmpTail = xw, gKmpLength = Nothing, gKmpPrev = pks}
k = GenericKmpState{gKmpTail = xs, gKmpLength = Nothing, gKmpPrev = pks}
pks = pk:ks
ks = k:go k xs
in ks
where
go _ [] = []
go pk (x:xs) = let k = recurse pk x xs
in k:go k xs
recurse GenericKmpState{gKmpLength = kl, gKmpPrev = kpw@(kp@GenericKmpState{gKmpTail = kpt:_}:kps)} x xs
| kpt == x = GenericKmpState{gKmpTail = xs, gKmpLength = Just $ maybe 1 (+ 1) kl, gKmpPrev = kps}
| isNothing kl = GenericKmpState{gKmpTail = xs, gKmpLength = Just 0, gKmpPrev = kpw}
| otherwise = recurse kp x xs
gKmpTraverseBy :: Num i => (a -> a -> Bool) -> [a] -> [GenericKmpState i a]
gKmpTraverseBy eq [] = []
gKmpTraverseBy eq xw@(_:xs) = let
pk = GenericKmpState{gKmpTail = xw, gKmpLength = Nothing, gKmpPrev = pks}
k = GenericKmpState{gKmpTail = xs, gKmpLength = Nothing, gKmpPrev = pks}
pks = pk:ks
ks = k:go eq k xs
in ks
where
go _ _ [] = []
go eq pk (x:xs) = let k = recurse eq pk x xs
in k:go eq k xs
recurse eq GenericKmpState{gKmpLength = kl, gKmpPrev = kpw@(kp@GenericKmpState{gKmpTail = kpt:_}:kps)} x xs
| kpt `eq` x = GenericKmpState{gKmpTail = xs, gKmpLength = Just $ maybe 1 (+ 1) kl, gKmpPrev = kps}
| isNothing kl = GenericKmpState{gKmpTail = xs, gKmpLength = Just 0, gKmpPrev = kpw}
| otherwise = recurse eq kp x xs