演習第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 2026 ExpyDoc