Skip to content

Instantly share code, notes, and snippets.

@kolmodin
Forked from rojepp/gist:2405633
Created April 17, 2012 17:40
Show Gist options
  • Save kolmodin/2407705 to your computer and use it in GitHub Desktop.
Save kolmodin/2407705 to your computer and use it in GitHub Desktop.
Levenshtein imp vs memo rec
import qualified Data.ByteString as B
import qualified Data.ByteString.Unsafe as B
import Control.Applicative
import Control.Monad.ST
import Data.Array.Base ( unsafeRead, unsafeWrite )
import Data.Array.ST
dist :: B.ByteString -> B.ByteString -> Int
dist str1 str2 =
case (B.length str1, B.length str2) of
(0,m) -> m
(n,0) -> n
(n,m) -> runST $ do
let row p c j
| j > m = unsafeRead p n
| otherwise = do
let !char = B.unsafeIndex str2 (j-1)
unsafeWrite c 0 j
column p c char 1
row c p (j+1)
column p c char i
| i > n = return ()
| otherwise = do
let !cost = if B.index str1 (i-1) == char then 0 else 1
m1 <- (+1) <$> unsafeRead c (i-1)
m2 <- (+1) <$> unsafeRead p i
m3 <- (+cost) <$> unsafeRead p (i-1)
unsafeWrite c i (min3 m1 m2 m3)
column p c char (i+1)
p <- newListArray (0,n+1) [0..n+1] :: ST s (STUArray s Int Int)
c <- newListArray (0,n+1) (repeat 0) :: ST s (STUArray s Int Int)
row p c 1
where
min3 a b c = min a (min b c)
let levenshteinm (s:string) (t:string) =
let c = new Dictionary<_,_>()
let rec memo i j =
match c.TryGetValue((i,j)) with
| true, x -> x
| _ ->
let r =
match (i,j) with
| (i,0) -> i
| (0,j) -> j
| (i,j) ->
if s.[i-1] = t.[j-1] then memo (i-1) (j-1)
else
let d1, d2, d3 = memo (i-1) j, memo i (j-1), memo (i-1) (j-1) in
1 + min d1 (min d2 d3)
c.Add((i,j), r)
r
memo (String.length s) (String.length t)
let levenshteini (a:string) (b:string) : int =
let inline min3 (a:int) b c = min a (min b c)
match a.Length, b.Length with
| 0, m -> m
| n, 0 -> n
| n, m ->
// mutable excuse: it is internal and it avoids Array copy in favor of swap.
let mutable p = Array.init (n+1) id // previous
let mutable d = Array.create (n+1) 0 // current
for j = 1 to m do
let c = b.[j-1]
d.[0] <- j
for i = 1 to n do
let cost = if a.[i-1] = c then 0 else 1
d.[i] <- min3 (d.[i-1] + 1) (p.[i] + 1) (p.[i-1] + cost)
let _d = p
p <- d
d <- _d
p.[n]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment