演習第2回 最終変更 7/14 本講義の評価 試験 演習第2回 演習第2回: 文字列検索 入力: A : 参照文字列 (長い) q1, q2, …, qm : 問い合わせ文字列(短いのがたくさん) 出力: 各qmに対してその出現位置すべて(ない場合もある) 基本的な解法は今後説明するが, “Suffix Array”という手法 を使う. 以下が要素技術 整列 2分探索 進行 おそらく来週(7/11)に説明を終え, その次再来週(7/16 (土曜 日))に演習を行う 一回で完了するものではない.その後も課題として継続する 「大きなデータを高速に」処理できることに情熱を燃やす.そ のためにあらゆる工夫をすることを期待する アルゴリズム プログラミング上の工夫 結果(速度)を報告するウェブページを設けて, 途中結果を共 有する 後日まとめのレポートを提出 Suffix (ある文字列Aの)接尾辞(suffix)とは, その文字列のある部分 から最後までの部分文字列を言う 例: 「も」「もも」「すもも」はどれも「すもも」のsuffix Aをn文字の文字列としたとき, Aのsuffixは明らかにn個ある i文字目から最後までのsuffixを Siと書くことにする 例: A = すもも S0 = すもも S1= もも S2=も Suffix Array (ある文字列Aの)接尾辞配列(suffix array) とは, 0, 1, …, n – 1 を以下を満たす順序 <A で整列したものである i <A j Si <lex Sj ただし <lex は文字列の辞書式順序を表す 言い換え Aのsuffixを辞書式に整列し, その順序にしたがってsuffixの「 添え字」を整列させたもの i <A j Si <lex Sj 例: A = MOMOKO 0 M O M O K 1 O M O K O 2 M O K O 3 O K O 4 K O 5 O O 4 K O 2 M O K O 0 M O M O K 5 O 3 O K O 1 O M O K O O 要するに 概念的にはAのsuffixすべてを整列させたもの ただし個々のsuffixは元の文字列における「位置」であらわさ れている 用途(検索)を考えれば当然 メモリ量の節約 作るべきもの二つ Aからsuffix array (以降SA)を作る関数 mk_suffix_array(“MOMOKO”, 6) { 4,2,0,5,3,1 } A, そのsuffix array SA, 問い合わせ文字列qが与えられたとき , qのAにおける出現位置を返す関数 sa_search(“MOMOKO”, {4,2,0,5,3,1}, “MO”) { 0, 2 } 注: 課題ではreference stringからquery stringを探索する以外 の規定はない. APIも, アルゴリズムも, (極端にいえばsuffix arrayを使うかどうかも)自分の判断で変更してよい 基本となる方法 mk_suffix_array(A, n) 0, 1, 2, …, n – 1 が一度ずつ現れる配列を準備 その配列を整列. ただしその際の「不等号(x < y)」の意味 を少しかえる x < y Sx <lex Sy sa_search(A, SA, q) SAを2分探索の要領で検索して, qをprefixに持つ(先頭部 分に含む)suffixを見つける. それには以下を満たすb, eを 見つける SSA[b] < q SSA[b+1] SSA[e] q < SSA[e+1] ここで < ()は, 最初の|q|文字だけを比べた(以降はないものとみな す)際の辞書式順序 b, eが見つかれば答えは { SA[b+1], SA[b+2], …, SA[e] } ただし問題の仕様ではこれを(整数として)小さい順に配列に格納 する. つまりAの中で前から現れる順に答える. sa_searchの図解 sa_search( “MOMOKO”, SA, “OK”) = { 3 } | “OK” | = 2 最初の2文字限定でsuffix arrayを2分探索 SSA[3] < q SSA[4] ( O < q OK) b = 3 SSA[4] q < SSA[5] (OK q < OM) e = 4 4 K O 2 M O K O 0 M O M O K 5 O 3 O K O 1 O M O K O O KO < OK MO < OK MO < OK O < OK OK = OK OK < OM 計算量は? mk_suffix_arrayはn要素の整列だからO(n log n)? sa_searchはn要素の2分探索だからO(log n)? どのようなAやqに「弱い」? それらを改良したアルゴリズムも知られている ライブラリの利用について 課題の趣旨から考えて“Suffix Array構築プログラム”をまる ごとどこかから拾ってくるとかいうのは当然ダメ 2分探索(bsearch), 整列(qsort)などを利用するのは?? これを自分で実装するというのも課題の趣旨なのでダメと します ただし, 「これを使わないとどうしてもできませんでした」と いう人に限り, それらを利用したプログラムの提出も認め る(注: おそらくbsearchは今回の目的には使えない) プログラムはいくつ提出してもよいことにする. 自分で作成 した版がある限り, 他の版でそれらの関数を用いるのも可 課題の趣旨は「色々試行錯誤, 頑張ること」 C言語ヒント Aを文字列とするとき, Aのi文字目以降は, A + i (もしくは &A[i])でOK (ポインタの足し算) A A+2 つまりsuffix SiはA + i でOK M O M O K O \0 二つの文字列A, Bを辞書式順序で比べるには, strcmp(A, B) 先頭 x 文字限定で比べるには, strncmp(A, B, x) これらは使ってもOK ただし自分で実装しても大した手間ではない 文字の比較は通常の < でOK 次回(7/16 土曜日)は演習の時間とする ただしそれ以前に作り始めることを期待 一回の時間内に終わる課題ではない Webページ準備中 m(_ _)m データ生成関数(Cで書かれたもの)を提供 練習用 本選計測用 自分で書いたプログラム中からそれらの関数を呼び出して利用 メモリぎりぎりの大きなデータを想定してください reference string ×5+ query strings = 1.5GBなど
© Copyright 2024 ExpyDoc