Skip to content

Instantly share code, notes, and snippets.

@ryukinix
Created July 13, 2017 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryukinix/6823eb9219a7f240588cadf41457b521 to your computer and use it in GitHub Desktop.
Save ryukinix/6823eb9219a7f240588cadf41457b521 to your computer and use it in GitHub Desktop.
KMP substring problem implementation on Common Lisp
;; kmp-fp: Substring Search @ HackerRank
;; Date: Thu 13 Jul 2017 08:48:40 AM -03
;; Manoel Vilela
;; NOTE: I'm programming in Common Lisp or in LOOP-MACRO?
(defun make-prefix-table (pattern length)
"Get the shift prefix array table to use on KMP
algorithm. This value is used to shift string comparison
on the next evaluation after a mismatch"
(loop with prefix-table = (make-array length :initial-element 0)
and prefix = 0
for i from 1 below length
do (loop while (and (> prefix 0)
(not (eq (aref pattern i)
(aref pattern prefix))))
do (setq prefix (aref prefix-table (1- prefix))))
when (eq (aref pattern i)
(aref pattern prefix))
do (incf prefix)
end
do (setf (aref prefix-table i) prefix)
finally (return prefix-table)))
(defun find-substring (pattern string)
"Using the KMP algorithm, find the position of the pattern in string if exists
Otherwise return nil."
(loop with string-length = (length string)
and pattern-length = (length pattern)
and string-index = 0
and pattern-index = 0
with prefix = (make-prefix-table pattern pattern-length)
while (< string-index string-length)
when (eq (aref string string-index)
(aref pattern pattern-index))
do (progn (incf string-index)
(incf pattern-index))
if (= pattern-index pattern-length)
return (- string-index pattern-index)
else
if (and (< string-index string-length)
(not (eq (aref string string-index)
(aref pattern pattern-index))))
if (/= pattern-index 0)
do (setq pattern-index (aref prefix (1- pattern-index)))
else
do (incf string-index)))
(defun main ()
(loop repeat (read)
for string = (read-line)
for pattern = (read-line)
for found = (find-substring pattern string)
for message = (if found "YES" "NO")
do (format t "~a~%" message)))
(main)
@phoe
Copy link

phoe commented Dec 8, 2019

Hey! What is the license of this code snippet? I'm looking for an implementation of KMP algorithm that I can use in Clozure Common Lisp which is licensed under Apache-2.0.

@ryukinix
Copy link
Author

ryukinix commented Dec 8, 2019

BSD. You can use freely. It's compatible with Apache license. You can find this same algorithm implementation in this library: https://github.com/ryukinix/leraxandria/blob/master/src/string/kmp-substring-search.lisp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment