Performance Damerau-Levenshtein距离的高效实现

Performance Damerau-Levenshtein距离的高效实现,performance,clojure,levenshtein-distance,Performance,Clojure,Levenshtein Distance,我试图实现真正高效的Clojure函数来计算。我决定使用(附带的源代码应该是C++)来计算Levenshtein距离,并添加一些行以使其适用于DLD 以下是我在Common Lisp中创建的内容(我希望它能有所帮助): 我最近不得不在clojure中编写一个高效的levenshtein距离函数来计算地面真相文本和ocr引擎结果之间的编辑。 递归实现的性能不足以快速计算两整页之间的levenshtein距离,因此我的实现使用动态编程。 它使用core.matrix来处理矩阵内容,而不是直接使用ja

我试图实现真正高效的Clojure函数来计算。我决定使用(附带的源代码应该是C++)来计算Levenshtein距离,并添加一些行以使其适用于DLD

以下是我在Common Lisp中创建的内容(我希望它能有所帮助):


我最近不得不在clojure中编写一个高效的levenshtein距离函数来计算地面真相文本和ocr引擎结果之间的编辑。 递归实现的性能不足以快速计算两整页之间的levenshtein距离,因此我的实现使用动态编程。 它使用core.matrix来处理矩阵内容,而不是直接使用java 2d数组。 为damerau levenshtein添加换位材料应该不难

(defn lev [str1 str2]
  (let [mat (new-matrix :ndarray (inc (count str1)) (inc (count str2)))
        len1 (count str1) len2 (count str2)]
   (mset! mat 0 0 0)
   (dotimes [i lein1]
     (mset! mat (inc i) 0 (inc i)))
   (dotimes [j len2]
     (mset! mat 0 (inc j) (inc j)))
   (dotimes [dj len2]
     (dotimes [di len1]
       (let [j (inc dj) i (inc di)]
         (mset! mat i j
              (cond
                (= (.charAt ^String str1 di) (.charAt ^String str2 dj))
                (mget mat di dj)
                :else
                (min (inc (mget mat di j)) (inc (mget mat i dj))
                    (inc (mget mat di dj))))))))
   (mget mat len1 len2))))

希望这有帮助

好的,这应该可以做到(基于):

请注意,您需要的库不是标准的(尽管它的名称)。可以通过以下方式与Leiningen一起安装:

[net.mikera/core.matrix "0.29.1"]
该库位于命名空间
clojure.core.matrix
中。要“按原样”使用此解决方案,应将命名空间中的符号“添加”到命名空间中

(defn lev [str1 str2]
  (let [mat (new-matrix :ndarray (inc (count str1)) (inc (count str2)))
        len1 (count str1) len2 (count str2)]
   (mset! mat 0 0 0)
   (dotimes [i lein1]
     (mset! mat (inc i) 0 (inc i)))
   (dotimes [j len2]
     (mset! mat 0 (inc j) (inc j)))
   (dotimes [dj len2]
     (dotimes [di len1]
       (let [j (inc dj) i (inc di)]
         (mset! mat i j
              (cond
                (= (.charAt ^String str1 di) (.charAt ^String str2 dj))
                (mget mat di dj)
                :else
                (min (inc (mget mat di j)) (inc (mget mat i dj))
                    (inc (mget mat di dj))))))))
   (mget mat len1 len2))))
(defn da-lev [str1 str2]
  (let [l1 (count str1)
        l2 (count str2)
        mx (new-matrix :ndarray (inc l1) (inc l2))]
   (mset! mx 0 0 0)
   (dotimes [i l1]
     (mset! mx (inc i) 0 (inc i)))
   (dotimes [j l2]
     (mset! mx 0 (inc j) (inc j)))
   (dotimes [i l1]
     (dotimes [j l2]
       (let [i+ (inc i) j+ (inc j)
             i- (dec i) j- (dec j)
             cost (if (= (.charAt str1 i)
                         (.charAt str2 j))
                    0 1)]
         (mset! mx i+ j+
                (min (inc (mget mx i j+))
                     (inc (mget mx i+ j))
                     (+ (mget mx i j) cost)))
         (if (and (pos? i) (pos? j)
                  (= (.charAt str1 i)
                     (.charAt str2 j-))
                  (= (.charAt str1 i-)
                     (.charAt str2 j)))
           (mset! mx i+ j+
                  (min (mget mx i+ j+)
                       (+ (mget mx i- j-) cost)))))))
   (mget mx l1 l2)))
[net.mikera/core.matrix "0.29.1"]