Duval's Algorithm
Duval's Algorithm computes a factorization of a word into a series of Lyndon Words with the property that .
(defun lyndon-factors (str)
"Compute the Lyndon factorization of STR."
(let ((i 0)
(s 0)
(e 1)
factors)
(while (< i (length str))
(setq s i)
(setq e (+ i 1))
(while (and (< e (length str)) (<= (elt str s) (elt str e)))
(if (< (elt str s) (elt str e))
(setq s i)
(setq s (+ s 1)))
(setq e (+ e 1)))
(while (<= i s)
(push (substring str i (+ i (- e s))) factors)
(setq i (+ i (- e s)))))
(nreverse factors)))
(lyndon-factors "abaababaabaaba")(require 're-builder)
(defvar lyndon-mode-overlays nil
"List of overlays used by `lyndon-mode'.")
(defun lyndon-mode-delete-overlays ()
"Delete all `lyndon-mode' overlays in the current buffer."
(mapc 'delete-overlay lyndon-mode-overlays)
(setq lyndon-mode-overlays nil))
(defun lyndon-mode-update-overlays ()
"Compute the Lyndon factorization of the current buffer, and update overlays."
(interactive)
(lyndon-mode-delete-overlays)
(save-excursion
(goto-char (point-min))
(let ((nface 0)
s e)
(while (not (eobp))
(setq s (point))
(setq e (1+ (point)))
(while (and (< e (point-max)) (<= (char-after s) (char-after e)))
(if (< (char-after s) (char-after e))
(setq s (point))
(setq s (1+ s)))
(setq e (1+ e)))
(while (<= (point) s)
(let ((overlay (make-overlay (point) (+ (point) (- e s))))
(face (intern (format "reb-match-%d" nface))))
(overlay-put overlay 'face face)
(push overlay lyndon-mode-overlays)
(setq nface (mod (1+ nface) 4))
(forward-char (- e s))))))))
(defun lyndon-mode-after-change (_start _end _len)
"Shim `lyndon-mode-update-overlays' for `after-change-functions'."
(lyndon-mode-update-overlays))
;;;###autoload
(define-minor-mode lyndon-mode
"Display the lyndon factorization of the current buffer."
:lighter "Lyndon"
(if lyndon-mode
(progn
(add-hook 'after-change-functions #'lyndon-mode-after-change nil t)
(lyndon-mode-update-overlays))
(lyndon-mode-delete-overlays)
(remove-hook 'after-change-functions #'lyndon-mode-after-change t)))