提出 #6107568
ソースコード 拡げる
;; -*- coding: utf-8 -*-
(eval-when (:compile-toplevel :load-toplevel :execute)
(defparameter OPT
#+swank '(optimize (speed 3) (safety 2))
#-swank '(optimize (speed 3) (safety 0) (debug 0)))
#+swank (progn (ql:quickload '(:cl-debug-print :fiveam))
(shadow :run)
(use-package :fiveam))
#-swank (set-dispatch-macro-character #\# #\> (lambda (s c p) (declare (ignore c p)) (read s nil (values) t))))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)
;; BEGIN_INSERTED_CONTENTS
(defmacro with-output-buffer (&body body)
"Buffers all outputs to *STANDARD-OUTPUT* in BODY and flushes them to
*STANDARD-OUTPUT* after BODY has been done (without error). Note that only
BASE-CHAR is allowed."
(let ((out (gensym)))
`(let ((,out (make-string-output-stream :element-type 'base-char)))
(let ((*standard-output* ,out))
,@body)
(write-string (get-output-stream-string ,out)))))
(declaim (ftype (function * (values fixnum &optional)) read-fixnum))
(defun read-fixnum (&optional (in *standard-input*))
(declare #.OPT)
(macrolet ((%read-byte ()
`(the (unsigned-byte 8)
#+swank (char-code (read-char in nil #\Nul))
#-swank (sb-impl::ansi-stream-read-byte in nil #.(char-code #\Nul) nil))))
(let* ((minus nil)
(result (loop (let ((byte (%read-byte)))
(cond ((<= 48 byte 57)
(return (- byte 48)))
((zerop byte) ; #\Nul
(error "Read EOF or #\Nul."))
((= byte #.(char-code #\-))
(setf minus t)))))))
(declare ((integer 0 #.most-positive-fixnum) result))
(loop
(let* ((byte (%read-byte)))
(if (<= 48 byte 57)
(setq result (+ (- byte 48) (* 10 (the (integer 0 #.(floor most-positive-fixnum 10)) result))))
(return (if minus (- result) result))))))))
;;;
;;; Rolling hash
;;;
;; TODO: handle multiple moduli together
(defstruct (rhash (:constructor %make-rhash (divisor cumul powers)))
(divisor 1000000007 :type (unsigned-byte 32))
(cumul nil :type (simple-array (unsigned-byte 32) (*)))
(powers nil :type (simple-array (unsigned-byte 32) (*))))
(defun make-rhash (vector divisor &key (key #'char-code) base)
"Returns the table of rolling-hash of VECTOR modulo DIVISOR. KEY is applied to
each element of VECTOR prior to computing the hash value.
DIVISOR := unsigned 32-bit prime number
BASE := 1 | 2 | ... | DIVISOR - 1
KEY := function returning FIXNUM"
(declare #.OPT
(vector vector)
((unsigned-byte 32) divisor)
((or null (unsigned-byte 32)) base)
(function key))
(assert (sb-int:positive-primep divisor))
(let* ((base (or base (+ 1 (random (- divisor 1)))))
(size (length vector))
(cumul (make-array (+ 1 size) :element-type '(unsigned-byte 32)))
(powers (make-array (+ 1 size) :element-type '(unsigned-byte 32))))
(assert (<= 1 base (- divisor 1)))
(setf (aref powers 0) 1)
(dotimes (i size)
(setf (aref powers (+ i 1))
(mod (* (aref powers i) base) divisor))
(let ((sum (+ (mod (* (aref cumul i) base) divisor)
(mod (the fixnum (funcall key (aref vector i))) divisor))))
(setf (aref cumul (+ i 1))
(if (> sum divisor)
(- sum divisor)
sum))))
(%make-rhash divisor cumul powers)))
(declaim (inline rhash-query)
(ftype (function * (values (unsigned-byte 32) &optional)) rhash-query))
(defun rhash-query (rhash l r)
"Returns the hash value of the interval [L, R)."
(declare ((integer 0 #.most-positive-fixnum) l r))
(assert (<= l r))
(let ((cumul (rhash-cumul rhash))
(powers (rhash-powers rhash))
(divisor (rhash-divisor rhash)))
(let ((res (+ (aref cumul r)
(- divisor (mod (* (aref cumul l) (aref powers (- r l))) divisor)))))
(if (> res divisor)
(- res divisor)
res))))
(declaim (inline rhash-concat))
(defun rhash-concat (rhash hash1 hash2 hash2-length)
(declare ((unsigned-byte 32) hash1 hash2)
((integer 0 #.most-positive-fixnum) hash2-length))
(let* ((divisor (rhash-divisor rhash)))
(mod (+ hash2
(mod (* hash1
(aref (rhash-powers rhash) hash2-length))
divisor))
divisor)))
(declaim (inline rhash-get-lcp))
(defun rhash-get-lcp (rhash1 start1 rhash2 start2)
(declare ((integer 0 #.most-positive-fixnum) start1 start2))
(assert (= (rhash-divisor rhash1) (rhash-divisor rhash2)))
(assert (and (< start1 (length (rhash-cumul rhash1)))
(< start2 (length (rhash-cumul rhash2)))))
(let ((max-length (min (- (length (rhash-cumul rhash1)) start1 1)
(- (length (rhash-cumul rhash2)) start2 1))))
(if (= (rhash-query rhash1 start1 (+ start1 max-length))
(rhash-query rhash2 start2 (+ start2 max-length)))
max-length
(labels ((bisect (ok ng)
(declare ((integer 0 #.most-positive-fixnum) ok ng))
(if (<= (- ng ok) 1)
ok
(let ((mid (ash (+ ng ok) -1)))
(if (= (rhash-query rhash1 start1 (+ start1 mid))
(rhash-query rhash2 start2 (+ start2 mid)))
(bisect mid ng)
(bisect ok mid))))))
(bisect 0 max-length)))))
(defmacro dbg (&rest forms)
#+swank
(if (= (length forms) 1)
`(format *error-output* "~A => ~A~%" ',(car forms) ,(car forms))
`(format *error-output* "~A => ~A~%" ',forms `(,,@forms)))
#-swank (declare (ignore forms)))
(defmacro define-int-types (&rest bits)
`(progn
,@(mapcar (lambda (b) `(deftype ,(intern (format nil "UINT~A" b)) () '(unsigned-byte ,b))) bits)
,@(mapcar (lambda (b) `(deftype ,(intern (format nil "INT~A" b)) () '(signed-byte ,b))) bits)))
(define-int-types 2 4 7 8 15 16 31 32 62 63 64)
(declaim (inline println))
(defun println (obj &optional (stream *standard-output*))
(let ((*read-default-float-format* 'double-float))
(prog1 (princ obj stream) (terpri stream))))
(defconstant +mod+ 1000000007)
;; Body
(declaim (ftype (function * (values uint32 &optional)) concat))
(defun concat (rhash l r pos char)
(declare #.OPT (uint32 l r pos))
(assert (<= l r))
(if (and (<= l pos) (< pos r))
(rhash-concat rhash
(rhash-concat rhash (rhash-query rhash l pos) (char-code char) 1)
(rhash-query rhash (+ pos 1) r)
(- r pos 1))
(rhash-query rhash l r)))
(defun main ()
(declare #.OPT)
(let* ((s (coerce (read-line) 'simple-base-string))
(q (read))
(rhash1 (make-rhash s 1000000007))
(rhash2 (make-rhash s 1000000009)))
(declare (uint32 q)
(simple-base-string s))
(with-output-buffer
(dotimes (i q)
(let* ((l (- (read-fixnum) 1))
(r (read-fixnum))
(period (read-fixnum))
(lcp (min (rhash-get-lcp rhash1 l rhash1 (+ l period))
(rhash-get-lcp rhash2 l rhash2 (+ l period)))))
(declare (uint32 l r period lcp))
;; #>lcp
(if (or (>= lcp (- r l period))
(and (= (concat rhash1 l (- r period) (+ l lcp) (aref s (+ l period lcp)))
(concat rhash1 (+ l period) r (+ l lcp) (aref s (+ l period lcp))))
(= (concat rhash2 l (- r period) (+ l lcp) (aref s (+ l period lcp)))
(concat rhash2 (+ l period) r (+ l lcp) (aref s (+ l period lcp)))))
(and (= (concat rhash1 l (- r period) (+ l period lcp) (aref s (+ l lcp)))
(concat rhash1 (+ l period) r (+ l period lcp) (aref s (+ l lcp))))
(= (concat rhash2 l (- r period) (+ l period lcp) (aref s (+ l lcp)))
(concat rhash2 (+ l period) r (+ l period lcp) (aref s (+ l lcp))))))
(write-line "Yes")
(write-line "No")))))))
#-swank(main)
提出情報
| 提出日時 | |
|---|---|
| 問題 | F - ほぼ周期文字列 |
| ユーザ | sansaqua |
| 言語 | Common Lisp (SBCL 1.1.14) |
| 得点 | 100 |
| コード長 | 8544 Byte |
| 結果 | AC |
| 実行時間 | 389 ms |
| メモリ | 46184 KiB |
ジャッジ結果
| セット名 | Sample | All | ||||
|---|---|---|---|---|---|---|
| 得点 / 配点 | 0 / 0 | 100 / 100 | ||||
| 結果 |
|
|
| セット名 | テストケース |
|---|---|
| Sample | sample_01.txt, sample_02.txt |
| All | sample_01.txt, sample_02.txt, subtask1_01.txt, subtask1_02.txt, subtask1_03.txt, subtask1_04.txt, subtask1_05.txt, subtask1_06.txt, subtask1_07.txt, subtask1_08.txt, subtask1_09.txt, subtask1_10.txt, subtask1_11.txt, subtask1_12.txt, subtask1_13.txt, subtask1_14.txt, subtask1_15.txt, subtask1_16.txt, subtask1_17.txt, subtask1_18.txt, subtask1_19.txt, subtask1_20.txt, subtask1_21.txt, subtask1_22.txt, subtask1_23.txt, subtask1_24.txt, subtask1_25.txt, subtask1_26.txt, subtask1_27.txt, subtask1_28.txt, subtask1_29.txt, subtask1_30.txt, subtask1_31.txt, subtask1_32.txt, subtask1_33.txt, subtask1_34.txt, subtask1_35.txt, subtask1_36.txt, subtask1_37.txt |
| ケース名 | 結果 | 実行時間 | メモリ |
|---|---|---|---|
| sample_01.txt | AC | 335 ms | 46184 KiB |
| sample_02.txt | AC | 160 ms | 33380 KiB |
| subtask1_01.txt | AC | 334 ms | 37732 KiB |
| subtask1_02.txt | AC | 335 ms | 37732 KiB |
| subtask1_03.txt | AC | 325 ms | 37736 KiB |
| subtask1_04.txt | AC | 312 ms | 37732 KiB |
| subtask1_05.txt | AC | 362 ms | 37732 KiB |
| subtask1_06.txt | AC | 309 ms | 37732 KiB |
| subtask1_07.txt | AC | 335 ms | 37736 KiB |
| subtask1_08.txt | AC | 334 ms | 37732 KiB |
| subtask1_09.txt | AC | 330 ms | 37864 KiB |
| subtask1_10.txt | AC | 320 ms | 37732 KiB |
| subtask1_11.txt | AC | 276 ms | 37864 KiB |
| subtask1_12.txt | AC | 357 ms | 37732 KiB |
| subtask1_13.txt | AC | 360 ms | 37732 KiB |
| subtask1_14.txt | AC | 358 ms | 37732 KiB |
| subtask1_15.txt | AC | 358 ms | 37736 KiB |
| subtask1_16.txt | AC | 380 ms | 37736 KiB |
| subtask1_17.txt | AC | 367 ms | 37732 KiB |
| subtask1_18.txt | AC | 370 ms | 37732 KiB |
| subtask1_19.txt | AC | 374 ms | 37732 KiB |
| subtask1_20.txt | AC | 378 ms | 37732 KiB |
| subtask1_21.txt | AC | 378 ms | 37728 KiB |
| subtask1_22.txt | AC | 376 ms | 37736 KiB |
| subtask1_23.txt | AC | 376 ms | 37732 KiB |
| subtask1_24.txt | AC | 378 ms | 37732 KiB |
| subtask1_25.txt | AC | 387 ms | 37732 KiB |
| subtask1_26.txt | AC | 382 ms | 37732 KiB |
| subtask1_27.txt | AC | 376 ms | 37732 KiB |
| subtask1_28.txt | AC | 368 ms | 37736 KiB |
| subtask1_29.txt | AC | 370 ms | 37728 KiB |
| subtask1_30.txt | AC | 372 ms | 37732 KiB |
| subtask1_31.txt | AC | 383 ms | 37736 KiB |
| subtask1_32.txt | AC | 377 ms | 37732 KiB |
| subtask1_33.txt | AC | 386 ms | 37732 KiB |
| subtask1_34.txt | AC | 375 ms | 37728 KiB |
| subtask1_35.txt | AC | 385 ms | 37728 KiB |
| subtask1_36.txt | AC | 389 ms | 37732 KiB |
| subtask1_37.txt | AC | 386 ms | 37732 KiB |