記憶一個地圖,此功能是遠遠超過它的遞歸版本速度更快:簡化使用lambda表達式,並在國家單子
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%確定簽名應該是什麼樣子(第二個問題)。
我想到了這個,狀態是「下一對要測量的字符串」,距離包含記憶的距離。
editDistance :: State Distances (String,String) -> State Distances()?
順便說一下,你的'emptyMap'和['Map.empty'](http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.html#五:空)。 – dave4420 2012-04-01 11:01:09