【发布时间】:2012-04-01 08:39:02
【问题描述】:
这个函数比它的递归版本快得多:
crossSubstrings :: String -> String -> [(String,String)]
crossSubstrings string1 string2 = [(substr1,substr2) | substr1 <- inits string1,
substr2 <- inits string2]
type Distances = Map.Map (String,String) Int
editDistanceMemoized :: String -> String -> Int
editDistanceMemoized s1 s2 =
let
substrings = s1 `crossSubstrings` s2
distances = foldl (editDistance) emptyMap substrings
in
distances Map.! (s1,s2)
where
emptyMap = Map.fromList []
editDistance :: Distances -> (String,String) -> Distances
editDistance map ([],s1) = map `Map.union` getMap [] s1 (length s1)
editDistance map (s1,[]) = map `Map.union` getMap s1 [] (length s1)
editDistance map (s1,s2) = map `Map.union` getMap s1 s2 (cost map s1 s2)
getMap s1 s2 d = Map.fromList [((s1,s2),d)]
insertionPCost = \m -> \s1 -> \s2 -> m Map.! (s1, init s2) + 1
deletionPCost = \m -> \s1 -> \s2 -> m Map.! (init s1, s2) + 1
substitutionPCost = \m -> \s1 -> \s2 -> m Map.! (init s1, init s2)
+ substitutionCostIfNEQ s1 s2
substitutionCostIfNEQ = \s1 -> \s2 -> if (last s1 == last s2) then 0 else 2
cost = \m -> \s1 -> \s2 -> minimum [insertionPCost m s1 s2,
deletionPCost m s1 s2,
substitutionPCost m s1 s2]
但是(第一个问题),我觉得可以避免一些 lambda(它看起来不是重复的吗?特别看cost)。有没有办法写minimum?
此外,State Monad 可用于传播地图(而不是使用foldl?)。尽管阅读了 State.>>= 和 State.id 的行为方式,但我不能 100% 确定签名应该是什么样子(第二个问题)。
我想到了这个,状态是“下一对要测量的字符串”,而 Distances 包含记忆的距离。
editDistance :: State Distances (String,String) -> State Distances ()?
【问题讨论】:
-
顺便提一下,您的
emptyMap与Map.empty相同。
标签: haskell memoization