方案中的LCS(最长公共子序列)

时间:2018-07-01 13:17:47

标签: scheme lcs

我尝试使用Scheme实现LCS算法,但是有一个错误。

(定义X   (列表#\ A#\ B#\ C#\ B#\ D#\ A#\ B))

(定义Y   (列表#\ B#\ D#\ C#\ A#\ B#\ A))

(定义前缀   (lambda(i s)     (如果(= i 0)       '()       (缺点(汽车)             (前缀(-i 1)                     (cdr s)))))))

(定义(选择)   (如果(= ith 1)     (汽车)     (选择(第1个)           (cdr s))))

(定义(LCS x y)   (定义(最佳i j)     (cond((或(= i 0)                (= j 0))            0)           ((eq?(pick i x)                 (选择j y))            (+1               (最佳(-i 1)                        (-j 1))))           (否则(最大值(LCS(前缀(-i 1)x)y)                      (LCS x(前缀(-j 1)y))))))   (最佳(长度x)            (长度y)))

  

1] =>(加载“ lcs.scm”)

     

;正在加载“ lcs.scm” ...完成   ;值:lcs

     

1] =>(lcs X Y)

     

;值:5

结果应该是4,我不知道错误在哪里。

1 个答案:

答案 0 :(得分:0)

您收到错误消息,因为最终的最佳递归调用不正确。 您将i-1的前缀xj-1的前缀y当作其他前缀。 ji可能小于相应字符串的长度,因此,您需要相应地在参数前加上前缀。

以下代码正常工作。

(define (LCS x y)
  (define (optimal i j)
    (cond
      ((or (= i 0) (= j 0)) 0)
      ((eq? (pick i x) (pick j y)) (+ 1 (optimal (- i 1) (- j 1))))
      (else (max (LCS (prefix (- i 1) x) (prefix j y)) (LCS (prefix i x) (prefix (- j 1) y))))))
  (optimal (length x) (length y)))

请注意,此问题仅存在是因为您混用了两种不同类型的呼叫。一个在前缀上调用LCS,另一个在i和j较小的情况下调用optimal。 您可以将最佳的LCS调用替换为更简单的解决方案。

(define (LCS x y)
  (define (optimal i j)
    (cond
      ((or (= i 0) (= j 0)) 0)
      ((eq? (pick i x) (pick j y)) (+ 1 (optimal (- i 1) (- j 1))))
      (else (max (optimal (- i 1) j) (optimal i (- j 1))))))
  (optimal (length x) (length y)))