レッスン
理論 — トライ木:接頭辞をたどって学ぶ
トライ木は接頭辞木とも呼ばれ、単語の集合を、異なる接頭辞ごとにノードを持つ木で表します。根は空の接頭辞を表し、各辺に一文字が対応します。根からノードまでの経路に沿って文字を読むと、そのノードが表す接頭辞になります。その接頭辞自体が格納された単語なら、ノードに終端の印を付けます。語頭が共通する単語は、その部分の経路を共有します。検索では、根から単語の文字を順にたどります。前方一致検索では、指定した接頭辞のノードまで進み、そこを根とする部分木から、印の付いたノードをすべて拾います。このデータ構造をtrieと名付けたのは、1960年のエドワード・フレドキンです。retrievalから取った名前で、treeと同じ発音を意図していました。
各記号の意味
W- リストにある単語の総数
L- 全単語の文字数の合計
N- 異なる接頭辞ごとに置くノードの総数(根を除く)
- 前提
- 文字は小文字のa〜zで、各文字は1バイト、ポインタは64ビットとします。どちらのデータ構造でも、パディングやメモリ割り当ての管理領域は数えません。二分探索では、比較した文字の組を一組ずつ数え、異なる文字が現れたところで比較を止めます。単語の末尾に達したことの確認には、追加のコストを数えません。ハッシュ表は、最も都合のよい、衝突がまったくない場合を扱います。18バイトのノードでは子をアルファベット順に並べているので、順に探して目当ての文字を通り過ぎたら、そこで探索を止めます。
全プロセスの詳細解説
-
どこまで共有できれば、トライ木のほうが小さくなる? 4 ステップ
長い単語を押してみましょう。85文字が21ノードに収まり、文字の4分の3を共有していても、18バイトのノードを使うトライ木は396バイト、リストは157バイトです。すべての単語がk文字のリストを考えると、トライ木にとって最も有利なのは、可能な文字列をすべて格納する場合です。このページのバイト数の数え方では、トライ木が単純なリストより小さくなる最小のkはいくつでしょうか。
-
画面の例では、21ノードに根を加えて22 × 18 = 396バイト。リストは85文字に加え、8語のそれぞれに終端の1バイトと8バイトのポインタを使うので、85 + 9 × 8 = 157バイトです。
-
k文字の文字列は全部で26k通りあります。それぞれk文字なので、リストに必要なのは(k + 9) × 26kバイトです。
-
トライ木では、1文字からk文字までのすべての文字列に対応するノードが必要です。その数は26 + 26² + … + 26kで、26/25 × 26kを少し下回ります。根を加えて18を掛けると、必要な容量は18.72 × 26kバイト弱です。
-
したがって、k + 9が18.72を超えるとリストのほうが大きくなり、最初にそうなるのはk = 10です。k = 9ではトライ木のほうが4.0%大きく、k = 10では1.5%小さくなります。
解答
答えは10文字。ただし、2610通りすべて、約1.4 × 1014語をリストに格納する場合です。209バイトのノードなら、同じ計算でk + 9が約217を超える必要があり、単語の長さは209文字になります。
-
学習の道すじ
データ構造が得意なこと
参考文献 (3)
- The name, its origin in "retrieval", and Fredkin's intended pronunciation, quoted in the definition: Paul E. Black, "trie", in Dictionary of Algorithms and Data Structures [online], Paul E. Black, ed., NIST, entry modified 12 February 2019.
- The paper that named the structure: Edward Fredkin, "Trie memory," Communications of the ACM 3(9), September 1960, pp. 490–499.
- The earlier description of searching on letter-by-letter keys: René de la Briandais, "File searching using variable length keys," Papers presented at the Western Joint Computer Conference, San Francisco, 3–5 March 1959, pp. 295–298.