[英]Knuth-Morris-Pratt algorithm in Scheme
这是在 Scheme 中计算失败 function(我们要多少步才能返回 go)的代码,当我们使用 Knuth-Morris-Pratt 算法时:
(define (compute-failure-function p)
(define n-p (string-length p))
(define sigma-table (make-vector n-p 0))
(let loop
((i-p 2)
(k 0))
(cond
((>= i-p n-p)
(vector-set! sigma-table (- n-p 1) k))
((eq? (string-ref p k)
(string-ref p (- i-p 1)))
(vector-set! sigma-table i-p (+ k 1))
(loop (+ i-p 1) (+ k 1)))
((> k 0)
(loop i-p (vector-ref sigma-table k)))
(else ; k=0
(vector-set! sigma-table i-p 0)
(loop (+ i-p 1) k))))
(vector-set! sigma-table 0 -1)
(lambda (q)
(vector-ref sigma-table q)))
但是我不明白k > 0
的部分。 有人可以解释一下吗?
我看到您对命名let
的语法感到困惑。 这篇文章很好地解释了它是如何工作的,但也许一个语法更熟悉的例子会让事情变得更清楚。 以 Python 中的这段代码为例,它将 1 到 10 的所有整数相加:
sum = 0
n = 1
while n <= 10:
sum += n
n += 1
print(sum)
=> 55
现在让我们尝试以递归方式编写它,我将调用我的 function loop
。 这是完全等价的:
def loop(n, sum):
if n > 10:
return sum
else:
return loop(n + 1, n + sum)
loop(1, 0)
=> 55
在上面的例子中, loop
function实现了一次迭代,参数n
用来跟踪当前的position,参数sum
累加答案。 现在让我们编写完全相同的代码,但是在 Scheme 中:
(let loop ((n 1) (sum 0))
(cond ((> n 10) sum)
(else (loop (+ n 1) (+ n sum)))))
=> 55
现在我们已经定义了一个名为loop
的本地过程,然后自动调用它的参数n
和sum
的初始值为1
和0
。 当达到递归的基本情况时,我们返回sum
,否则我们继续调用这个过程,为参数传递更新的值。 它与 Python 代码中的完全相同。 不要被语法搞糊涂了。
在您的算法中, ip
和k
是迭代变量,分别初始化为2
和0
。 根据哪个条件为真,当我们使用ip
和k
的更新值再次调用loop
时迭代继续,或者当达到 case (>= ip np)
时迭代结束,此时循环退出并且计算值在变量sigma-table
。 该过程以返回一个新的 function 结束,称为“故障函数”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.