Skip to content

Instantly share code, notes, and snippets.

@tkych
Created December 13, 2013 11:32
Show Gist options
  • Save tkych/7943023 to your computer and use it in GitHub Desktop.
Save tkych/7943023 to your computer and use it in GitHub Desktop.
回文の発掘, saihon2013さんのエレガントな解答を参考に書き直しました。
;;;; Last modified: 2013-12-13 20:30:09 tkych
;; saihon2013さんのエレガントな解答を参考に書き直しました。
;;====================================================================
;; 回文の発掘 ver.2
;;====================================================================
;; - [回文の発掘 〜 横へな 2013.11.1 参考問題](http://nabetani.sakura.ne.jp/hena/ord15subpalin/)
;; - [第15回オフラインリアルタイムどう書くの参考問題](http://qiita.com/Nabetani/items/0b56395d4c9e7c64b230)
;; - [saihon2013さんの解答: kaibun.c](http://qiita.com/saihon2013/items/c7b8e94371326a621039)
;; - [shiracamusさんの解答: 第15回オフラインリアルタイムどう書くの参考問題をPythonで](http://qiita.com/shiracamus/items/49da2b5e7097892f48c9)
;;--------------------------------------------------------------------
;; Package
;;--------------------------------------------------------------------
(in-package :cl-user)
(defpackage :find-palindrome-v2 (:use :cl))
(in-package :find-palindrome-v2)
;;--------------------------------------------------------------------
;; Main
;;--------------------------------------------------------------------
(defun main (input)
(labels ((rec (first last num-match)
(let ((longest num-match))
(loop :for f :from first :below (length input) :do
(loop :for l :downfrom last :to f :do
(when (char= (char input f) (char input l))
(let ((match (rec (1+ f) (1- l)
(+ num-match (if (= f l) 1 2)))))
(when (> match longest)
(setf longest match))
(return)))))
longest)))
(write-to-string
(rec 0 (1- (length input)) 0))))
#| アルゴリズムの解説
入力文字列を "banana"とすると:
(main "banana") => "5"
0. first を固定し、first と last が一致するか、`first = last' となるまで、last を1つずつ前に動かす。
もし、first が文字列の最後に到達したら goto 2.
first last num-match = 0, longest = 0
| |
V V
b|a|n|a|n|a
first last num-match = 0, longest = 0
| |
V V
b|a|n|a|n|a
...
1-0. もし、first と last で一致するものがなく、`first = last' となった場合、first を一つ後ろに動かし、goto 0.
first last num-match = 0, longest = 0
|/
V
b|a|n|a|n|a
first last num-match = 0, longest = 0
| |
V V
b|a|n|a|n|a
1-1. もし、first と last が一致したら、first, last を1つずつ内側に動かし、num-match を増やし、goto 0(再帰).
( num-match を増やす際の条件、`first = last' は、いま着目している部分文字列の長さが奇数の場合)。
first last num-match = 2, longest = 0
| |
V V
b|a|n|a|n|a
first last num-match = 4, longest = 0
| |
V V
b|a|n|a|n|a
first last num-match = 5, longest = 0
\ /
V
b|a|n|a|n|a
再帰を抜ける際に num-match が longest より大きい場合、longest を num-match に更新する。
first last num-match = 0, longest = 5
| |
V V
b|a|n|a|n|a
2. first が最後に到達したら longest を返し終了。
first num-match = 0, longest = 5
|
V
b|a|n|a|n|a
|#
;;--------------------------------------------------------------------
;; Tests
;;--------------------------------------------------------------------
(defun =>? (got expected)
(assert (string= got expected)))
(time
(progn
(=>? (main "I_believe_you_can_solve") "9")
(=>? (main "a") "1")
(=>? (main "aa") "2")
(=>? (main "aaa") "3")
(=>? (main "ab") "1")
(=>? (main "aabb") "2")
(=>? (main "ABBA") "4")
(=>? (main "Abba") "2")
(=>? (main "1234567890") "1")
(=>? (main "1234567890987654321") "19")
(=>? (main "abcdcba") "7")
(=>? (main "0a1b2c3d4c5b6a7") "7")
(=>? (main "abcdcba0123210") "7")
(=>? (main "abcdcba_123210") "7")
(=>? (main "_bcdcba0123210") "7")
(=>? (main "abcddcba0123210") "8")
(=>? (main "abcdcba01233210") "8")
(=>? (main "a0bc1dc2ba3210a") "9")
(=>? (main "a0bc1ddc2ba3210") "8")
(=>? (main "3a0bc1ddc2ba3210") "10")
(=>? (main "11oooo1111o1oo1o111ooooooooooo") "20")
(=>? (main "11o1111o1111oo11ooo11111ooo1oo") "20")
(=>? (main "111111oo11o111ooo1o1ooo11ooo1o") "21")
(=>? (main "11o1o1o11oo11o11oo111o1o1o11oo") "27")
(=>? (main "oo111o1o11o1oo1ooo11o1o11o1o1o") "27")
(=>? (main "1o1oo11111o1o1oo1o1o1111oo1o1o") "28")
(=>? (main "QQooooQooooQQyQoyQQQyyyyQQoyoy") "15")
(=>? (main "oQoooQooooQyoyQoyoyyyQQyQQQQoQ") "16")
(=>? (main "yyyyyooyQyyyoyyQyyooyQoQoQQoQy") "17")
(=>? (main "yyQoyQoyyQyQQoyooooyyQQyQyooQy") "24")
(=>? (main "oQQooQoQyQQoyoQQoQyQyQyQoQoooo") "24")
(=>? (main "oQQyQQyyQyQQoooyQQyyyQQQyyQQoy") "25")
(=>? (main "WAk9iHI4jVDlStyudwTNqE138kwan2") "3")
(=>? (main "c43fIu1Mlz0K9hEVOgGcUdbeB5ksa7") "3")
(=>? (main "CAbYcW5VqHjzFdIkH_61PM0TsyRuie") "3")
(=>? (main "jInQnUvSayrJTsQWujovbbqW0STvoj") "10")
(=>? (main "iZDrvpUKgtj3FrZsZ4CLjrEgUdZzQG") "11")
(=>? (main "ROgYUOu6er_DA7nB6UGquO1GUHC62R") "11")
(=>? (main "Oh_be_a_fine_girl_kiss_me") "9")
(=>? (main "8086_6502_6809_Z80") "11")
(=>? (main "xcode_visualstudio_eclipse") "11")
(=>? (main "word_excel_powerpoint_outlook") "9")
(=>? (main "abcdefghijklmnopqrstuvwxyz0123") "1")
))
;;====================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment