コンピュータサイエンスにおいて、接尾辞配列とは、文字列のすべての接尾辞をソートした配列のことである。これは、全文索引、データ圧縮アルゴリズム、書誌計量学などの分野で用いられるデータ構造である。
接尾辞配列は、接尾辞ツリーに代わるシンプルで省スペースな方法として、Manber & Myers (1990)によって導入されました。これらは、1987 年にGaston GonnetによってPAT 配列という名前で独自に発見されていました( Gonnet、Baeza-Yates & Snider 1992 )。
Li、Li 、 Huo(2016)は、最初のインプレイス時間および空間の両方で最適な時間サフィックス配列構築アルゴリズム。ここで、インプレースとは、アルゴリズムが必要とするのは だけであることを意味する。入力文字列と出力接尾辞配列の外側にある追加スペース。
拡張サフィックス配列 (ESA) は、サフィックスツリーの完全な機能を再現し、同じ時間とメモリの複雑さを維持する追加のテーブルを備えたサフィックス配列です。[ 1 ] 文字列のすべてのサフィックスではなく、一部のサフィックスのみのソート済み配列は、スパースサフィックス配列と呼ばれます。[ 2 ]
させてになる-文字列にしてのサブストリングを表す範囲はに包括的。
接尾辞配列のは、接尾辞の開始位置を提供する整数の配列として定義されます。辞書順。つまり、エントリは開始位置が含まれています-th 最小の接尾辞そしてすべての:。
各接尾辞表示される正確に1回。接尾辞は単純な文字列です。これらの文字列は(紙の辞書のように)ソートされてから、開始位置(整数インデックス)が保存されます。。
テキストを検討してください=banana$インデックス化される:
テキストの末尾には、$他のどの文字よりも小さく、辞書的にも特別な番人文字が付けられています。テキストには以下の接尾辞が付いています。
これらの接尾辞は昇順に並べ替えることができます。
接尾辞配列ソートされたこれらの接尾辞の開始位置が含まれています。
接尾辞配列(分かりやすくするために、接尾辞を縦書きで下に表記):
例えば、値4を含み、したがって、位置4から始まる接尾辞を参照します。、これは接尾辞ですana$。
接尾辞配列は接尾辞木と密接に関連しています。
すべてのサフィックスツリーアルゴリズムは、追加情報( LCP配列など)で強化されたサフィックス配列を使用するアルゴリズムに体系的に置き換えることができ、同じ問題を同じ時間計算量で解決できることが示されています。[ 1 ] サフィックス配列のサフィックスツリーに対する利点には、スペース要件の改善、より単純な線形時間の構築アルゴリズム(例えば、ウッコネンのアルゴリズムと比較して)、およびキャッシュ局所性の改善などがあります。[ 3 ]
サフィックス配列は、サフィックスツリーのスペース要件を改善するために、 Manber & Myers (1990)によって導入されました。サフィックス配列は、整数。整数を仮定すると、バイト、サフィックス配列には合計バイト数。これは、慎重なサフィックスツリー実装に必要なバイト。[ 4 ]
しかし、特定のアプリケーションでは、サフィックス配列のスペース要件が依然として問題となる場合があります。ビット単位で分析すると、サフィックス配列はスペース、一方元のテキストはサイズのアルファベット上必要なのはビット。ヒトゲノムの場合そしてしたがって、接尾辞配列はゲノム自体よりも約16倍のメモリを占有することになる。
こうした不一致が、圧縮接尾辞配列や、FMインデックスなどのBWTベースの圧縮全文インデックスへの流れを促した。これらのデータ構造は、テキストのサイズ内、あるいはそれ以下のスペースしか必要としない。
接尾辞ツリーは以下のように構築できます。また、深さ優先でツリーを走査することにより、接尾辞配列に変換することもできます。なので、接尾辞配列を構築できるアルゴリズムが存在する。
接尾辞配列を構築する素朴なアプローチは、比較ベースのソートアルゴリズムを使用することです。これらのアルゴリズムは、接尾辞の比較ですが、接尾辞の比較は時間なので、このアプローチの全体的な実行時間は。
より高度なアルゴリズムは、ソートされる接尾辞が任意の文字列ではなく、互いに関連しているという事実を利用します。これらのアルゴリズムは、次の目標を達成しようとします。[ 5 ]
すべての目標を達成した最初のアルゴリズムの 1 つは、Nong、Zhang 、 Chan (2009)の SA-IS アルゴリズムです。このアルゴリズムは比較的単純 ( 100 LOC未満) で、 LCP 配列を同時に構築するように拡張できます。[ 6 ] SA-IS アルゴリズムは、既知のサフィックス配列構築アルゴリズムの中で最も高速なものの 1 つは、Yuta Mori [ 7 ]による慎重な実装により、他のほとんどの線形または超線形構築アプローチよりも優れたパフォーマンスを発揮します。
時間と空間の要件に加えて、接尾辞配列構築アルゴリズムは、サポートされるアルファベットによっても区別されます。 定数アルファベットではアルファベットのサイズが定数によって制限され、整数アルファベットでは文字が範囲に応じて整数になります。文字比較のみが許可される一般的なアルファベット。[ 8 ]
ほとんどの接尾辞配列構築アルゴリズムは、次のアプローチのいずれかに基づいています。[ 5 ]
整数アルファベットに対するよく知られた再帰アルゴリズムは、Kärkkäinen & Sanders (2003)のDC3 / skewアルゴリズムです。これは線形時間で実行され、並列[ 9 ]および外部メモリ[ 10 ]のサフィックス配列構築アルゴリズムの基礎として成功裏に使用されています。
Salson ら (2010)による最近の研究では、編集されたテキストの接尾辞配列をゼロから再構築するのではなく更新するアルゴリズムが提案されています。理論上の最悪の場合の時間計算量は実際にはうまく機能しているようです。著者らの実験結果によると、元のテキストに妥当な数の文字を挿入する場合、動的接尾辞配列の実装は再構築よりも一般的に効率的であることが示されています。
実際のオープンソース作業では、接尾辞配列の構築によく使われるルーチンは、1999 年の Larsson-Sadakane アルゴリズムに基づく qsufsort でした。[ 11 ]このルーチンは、2017 年時点で「メインメモリで知られている最速の接尾辞ソートアルゴリズム」である Yuta Mori の DivSufSort に取って代わられました。これも LCP 配列を計算するように変更できます。これは、Itoh-Tanaka と組み合わせた誘導コピーを使用します。[ 12 ] 2021 年に、Ilya Grebnov によってこのアルゴリズムのより高速な実装が発表されました。[ 13 ]これは、平均してSilesia コーパスでの DivSufSort 実装よりも 65% のパフォーマンス向上を示しました。[ 14 ]
接尾辞配列の概念は、複数の文字列に拡張できます。これは一般化接尾辞配列 (GSA) と呼ばれ、一連の文字列のすべての接尾辞 (たとえば、そして、各文字列のすべての接尾辞とともに辞書式順序でソートされます。[ 15 ]
文字列の接尾辞配列は、部分文字列パターンのすべての出現箇所を素早く見つけるためのインデックスとして使用できます。文字列内でパターンのすべての出現箇所を見つけることは、部分文字列で始まるすべての接尾辞を見つけることと同等です。辞書順のおかげで、これらの接尾辞は接尾辞配列にグループ化され、2つの二分探索で効率的に見つけることができます。最初の探索で区間の開始位置を特定し、2番目の探索で終了位置を決定します。
n = len ( S )def search ( P : str ) -> tuple [ int , int ]: """パターン P で始まる S のすべての接尾辞を表す 区間 A[s:r] (終了インデックスを除く) となるようなインデックス (s, r) を返します。 """ # 区間の開始位置を見つけるl = 0 # Python では、配列のインデックスは 0 から始まりますr = n while l < r : mid = ( l + r ) // 2 # 除算は最も近い整数に切り捨てます# suffixAt(A[i]) は i 番目に小さい接尾辞ですif P > suffixAt ( A [ mid ]): l = mid + 1 else : r = mid s = l# 区間の終了位置を見つけるr = n while l < r : mid = ( l + r ) // 2 if suffixAt ( A [ mid ]) . startswith ( P ): l = mid + 1 else : r = mid return ( s , r )部分文字列パターンを見つける長さ文字列の中で長さ取る時間、単一の接尾辞の比較には比較する必要がある文字。マンバーとマイヤーズ(1990)は、この境界をどのように改善できるかを説明しています。LCP情報を使用した時間。このアイデアは、パターンと現在の検索区間の最長共通接頭辞の一部であることがすでにわかっている場合、パターン比較で特定の文字を再比較する必要がないというものです。Abouelhoda 、Kurtz 、 Ohlebusch(2004)は、この上限をさらに改善し、検索時間を達成しました。接尾辞木から知られているように、一定のアルファベットサイズの場合。
接尾辞ソートアルゴリズムは、バロウズ・ウィーラー変換(BWT)の計算に使用できます。BWTでは、文字列のすべての巡回順列をソートする必要があります。文字列が、他のすべての文字よりも辞書順で小さい特別な文字列末尾文字(つまり、$)で終わる場合、ソートされた回転BWT行列の順序は、接尾辞配列内の接尾辞の順序に対応します。したがって、 BWTは、まずテキストの接尾辞配列を作成し、次にBWT文字列を推論することで、線形時間で計算できます。。
接尾辞配列は、例文ベースの機械翻訳で部分文字列を検索するためにも使用でき、統計的機械翻訳で使用される完全なフレーズテーブルよりもはるかに少ないストレージを必要とします。
接尾辞配列の多くの追加的な応用には、LCP配列が必要です。これらのいくつかは、 LCP配列の応用セクションで詳しく説明されています。
接尾辞木は、パターンマッチング、文字列マッチング、インデックス作成、テキスト統計などの分野で幅広く応用されている強力なデータ構造です。しかし、かなりのスペースを占有するため、ゲノム解析のように大量のデータを処理する必要がある多くのリアルタイムアプリケーションでは欠点となります。この欠点を克服するために、拡張接尾辞配列が開発されました。これは、接尾辞配列と、接尾辞木内のノード間の親子関係に関する情報を含む子テーブルと呼ばれる追加のテーブルで構成されるデータ構造です。この木のノード分岐データ構造はリンクリストです。拡張接尾辞配列は、スペース効率と時間計算量の両面で接尾辞木よりも優れており、実装も容易です。さらに、LCP-区間木と呼ばれる抽象概念を用いることで、接尾辞木を使用するあらゆるアルゴリズムに適用できます。長さのパターンを検索する時間計算量は拡張サフィックス配列では。
拡張接尾辞配列は、2つの配列で構成されています。
Sの接尾辞配列の場合、Sの接尾辞木の対応するノードに関連付けられたlcp間隔は次のように定義できます。
区間 [i,..j]、0 ≤ i ≤ j ≤ n は、lcp 値の lcp 区間です。
- lcptab[i] < l、
- lcptab[k] ≥ l すべての i + 1 ≤ k ≤ j に対して、
- lcptab[k] = l (i + 1 ≤ k ≤ j の場合)、l = n − i + 1 (i = j の場合)
- lcptab[j + 1] < l。
pos[i − 1] と pos[i] の最長共通接頭辞の長さが lcp[i] に格納されます。ここで 2 ≤ i ≤ n です。 lcp 区間は、S の接尾辞ツリー内の関連ノード間の親子関係と同じ関係を表します。これは、[i..j] の対応するノードが [k..l] の対応するノードの子である場合、lcp 区間 [i..j] は別の lcp 区間 [k..l] の子区間であることを示しています。[k..l] が [i..j] の子区間である場合、lcp 区間 [i..j] は lcp 区間 [k..l] の親区間です。
子テーブルcldtabは、 up、down、nextlIndex という3 つの n 個の配列で構成されています。対応するサフィックスツリーのエッジに関する情報は、up配列とdown配列に格納および維持されます。nextlIndex配列には、サフィックスツリーのノード分岐に使用されるリンクリスト内のリンクが格納されます。
up 、down 、nextlIndex配列は次のように定義されます。
ツリーのlcp区間を下から上に走査することで、子テーブルを線形時間で構築できます。アップ/ダウン値とnextlIndex値は、2つの異なるアルゴリズムを使用して個別に計算できます。
拡張サフィックス配列のサフィックスリンクは、前処理中に各区間 [i,..j] に対してサフィックスリンク区間 [ 1,..,r ] を生成することによって計算できます。区間の左要素 l と右要素 r は、[i,..,j] の最初のインデックスに保持されます。この区間のテーブルは 0 から n までです。サフィックスリンクテーブルは、lcp 区間ツリーの左から右への幅優先走査によって構築されます。l 区間が計算されるたびに、 l リストと呼ばれる l 区間のリストに追加されます。lcp 値が 0 より大きい場合、リスト内のすべてのl区間 [i,..,j] に対して、link[i] が計算されます。区間 [ l ,.., r ] は、 l がすべてのl -1 区間の中で最大の左境界である( l -1) リストでの二分探索によって計算されます。 [i,..j] の接尾辞リンク区間は、この区間 [ l,..,r ] で表されます。値lとrは最終的に [i,..,j] の最初のインデックスに格納されます。