トライ木、ある、また、キーツリーまたはトライとして知られている辞書のツリーは、ツリー構造、ハッシュツリーのバリエーションです。統計のための代表的なアプリケーション
や文字列のソート多数(文字列、これらに限定されない)が、それは多くの場合、テキスト検索エンジンシステムの単語頻度統計のために使用されています。その利点は以下のとおりです。最大の
最小化、不要な文字列比較、高効率のBi Haxi照会テーブル。
これは3つの基本的なプロパティがあります。
図2に示すように、そのノードに対応する文字列を接続する経路を介してルートノードからノードへ。
3、各ノードのすべての子ノードが含まれている文字は同じではありません。
問題:
単語が英語のストアテキストファイルにありますが、今、あなたがあれば、それは何度も表示され、与えられた単語の一部がファイル内に存在することがわかっている必要がありますか?
解決法1:
すべての単語がマップに格納されている場合は、それぞれの時間は、時間の複雑さはO(ログ(N))に縮小されて検索します。
すべての文字列の長さの合計を想定nは、ビルドトライ時間にはO(n)があります。:時間の複雑さがある見つける、あなたは文字列の長さをk見つけたいと仮定
O(K)(もO(1)に相当)。
タイトル:もはや10の言葉よりもあなたに10万与えません。各単語については、我々は最初のいくつかの場所に表示される最初の時間を求めがあった場合、彼は、登場出没判断しなければなりません。
分析:もちろん、この問題は解決するためにハッシュすることができますが、この記事では、理由は特定の方法でよりその使用、トライであるに焦点を当てています。例えば、1つのワードが、我々はそれの接頭語が登場するかどうかを聞いています。悪いアウトこのようハッシュでは、とトライして、それは非常に簡単です。
私たちは最も愚かな方法を使用している場合今すぐ戻っ例に、それがある場合は、各単語のために、私たちは言葉の前でそれを見て行かなければなりません。だから、このアルゴリズムの複雑さはO(N ^ 2)です。また、10万の範囲について明確に受け入れられません。今、私たちは思考の変化を求めています。私はB、C、D、に、その言葉で彼の前に、単語のクエリがABCDであると仮定のようなF Iは明らかに考慮される必要はありませんから始まります。そして、限り、それはそれがあるかどうかをabcdの表情で始まるよう。長い間、我々は第二の手紙としてBを考えると同様に、単語と初めに、何度も何度も範囲を狭めると、このようなAモデルツリーの関連性を向上させ、徐々に明らかになります。
同様にbは、ABC、ABDが、BCD、仮定 ABCD、EFG、HII の下に示されているこれらの6つの言葉、私たちはこの木を構築します:
上記のようにノードが赤色でマークされている場合、彼のプロセスのルートから横断各ノードの単語は、単語の存在を示す、または存在しない、です。
まあ、言葉のために、私は、ルートからこのノードは赤であなたはそれが前に現れたかどうかを知ることができますマークされているかどうかを見て彼の対応するノードを停止しました。このノードは赤でマークされ、言葉を挿入するのと同じです。
私たちのお問い合わせや挿入の結果は、一緒に(それが一緒にどのように行われるか、クエリと挿入強調経験は、後に詳細に説明)を完成させることができるように、費やした時間はわずかワード長で、このサンプルでは、10です。
私たちは、それぞれの層では、トライ木のノードを見ることができる26 ^ I-レベルです。スペースを節約するためにそう。我々は、動的にリンクされたリストを使用するか、またはシミュレートダイナミックに配列を使用しています。スペースは、語の単語の長さ×数よりも多く取りません。
四、トライ木アプリケーション:
(:大規模なデータ収集および処理の詳細ビットマップを内接する記事からの抜粋)がトライを解決するために適用することができ、本明細書に記載の前記問題の導入に加えて、トライは、問題を解決することができます。
- 図3に示すように、各行はワードである1Gのファイルサイズを有する、ワードサイズは、メモリの制限のサイズは1Mである、16以上のバイトではありません。100ワードの最高周波数を返します。
- 繰り返され、その一部9,1000ワン列、すべての削除を繰り返す必要は、まったく重複している文字列を保持していません。どのように設計し、実装するためにしてください?
- 10は、1万行、1行につき1つの単語についてのテキストファイルは、トップ10の最も頻繁に出現する単語の統計を必要とする、時間複雑分析与え、思考を与えてください。
- 13、人気の高いクエリを探して:検索エンジンで検索されたすべての文字列がログファイルにユーザーの用途が記録されるたびに取得します、それぞれ1〜255バイトのクエリ文字列の長さが。千万レコードがあると仮定すると、反復可能読み取りの合計数が10万人であるが、これらのクエリ文字列は、比較的高いが、重複の除去であれば、それ以上300万未満。より多くのユーザーが、より多くの人気を照会示す、クエリ文字列の繰り返しが高いです。10最も人気のあるクエリ文字列、必要なメモリ使用量の統計が1Gを超えることはできませんしてください。
(1)この問題を解決するためにあなたのアイデアを記載してください。
(2)は、メイン処理プロセス、アルゴリズム、およびアルゴリズムの複雑さを与えてください。
さまざまなトピックの詳細については解決するために行わトライノードメンテナンスを変更することができます
5つの例を説明します
入力
テストデータ入力の複数のグループを備え、各テストデータの行数を含みます。
入力の最初の行は、T(T <10)、Tは、全データセットを表す整数です。
各データの最初の行は、2つの正の整数N、M(<1 = N入力され 、M <= 100000)を、 次の行は、Nを正の整数であり、ゼウスのセットのための代表的な、その後、M行、各行が含ま正の整数S、プロメテウスを表す正の整数は尋ねました。すべての正の整数ではない以上2 ^ 32。
出力
データの各セットについて、あなたは出力単一行への最初の必要性「ケース#:?」、疑問符がデータセットの現在の数で満たされるために、グループの数は、開始から計算されます。
各クエリに対して、K、及びK整数正の出力は、最大値S XORように。サンプル入力
2 3 2 3 4 5 1 5 4 1 4 6 5 6 3
サンプル出力
ケース#1: 4 3 ケース#2: 4
ソリューション:
第一の入力数nに対して、第一その二分木と辞書を構築します。次に、m回のための問い合わせの数は、x、及び(低バイナリハイから離れて行く時間)対向ノードのビット値を取ることを試みるたびに、xは
コードが説明されています
コード:
1つの#include <iostreamの> 2の#include <cstdioを> 3。の#include <CStringの> 4。の#include <cstdlib> 5。の#include <アルゴリズム> 6。 使用した 名前空間STD; 7のtypedef 構造体トライ* TrieNode; // 注この行すなわち、以下の場合TrieNode変数はトライあるポインタ変数の型で宣言 8 構造体トライ 9。 { 10 INT ヴァル; 11 TrieNode次に[ 2 ]; 12は、 トライ() 13である { 14 =ヴァル0 ; 15 memsetの(次に、NULLは、はsizeof (NEXT)); 16 } 17 }; 18である 。19個の ボイドインサート(TrieNode根、INT X)// 2進数で低xに高い寄与からビット 20は 、{ 21は TrieNode P = ルート; 22である ため(INT I = 31であり ; I> = 0 ; i-- ) 23である { 24 INT T =(X >> I)が&1。; 25 IF(P->次に[T] == NULL)P->次に[T] = 新しい新しい 構造体トライ(); 26である P = P->次の[T]; 27 } 28 P->ヴァル= X; 29 } 30 31である INTクエリ(根、TrieNode INT X) 32 { 33は TrieNode P = ルート; 34である ため(INT I = 31であり、 I> =; 0 ; I - ) 35 { 36 int型 T =((X >>私は)&1。)^ 1。 ; // 我々は排他的論理和できるだけ大きくする最終的な答えをしたいので、とXOR演算であるため、「同じことが0です、 1 "は異なっている 37 // 、我々は検索を開始するために、高レベルからなので、私たちが歩くしようとする必要がありますので、進数(10000)は、進数(01111)よりも大きくなるように(!(X >> i)は& 1) その 38 // ノード。これは、(i)&1(X >>離れて行くだろう歩くことができない一つのノードのみです ) このノード 39 // ((X >> I)&1 ) のi番目の位置にxのバイナリ値で表され、 40 IF(P- >次に[T] == NULL)= T(X >> I)&1 ; 41で IF(P->次に[T])= P-P> 次に[T]、 42は 他の リターン - 。1 ; // 外出缶エンドの最後に 43である } 44は、 リターン P-> ;ヴァル 45 } 46は、 47 空隙デル(TrieNodeルート) // 各ツリーのノードを削除するために実行 48 { 49の ための(INT I = 0 ; I < 2; ++ I) 50 { 51 であれば(root->次に[i])とデル(root-> 次の[I])。 52 } 53 削除(ルート)。 54 } 55 56 のint main()の 57 { 58 int型、T、N、M、P = 0 。 59 のscanf(" %dの"、&T)。 60 一方(t-- ) 61 { 62 のprintf(" ケース#1%のD:\ n "、++ P); 63 TrieNodeルート=新しい 構造体トライ(); 64 のscanf(" %D%D "、&N、&M)。 65 のために(INT iは= 0 ; I <N ++ I) 66 { 67 のint T。 68 のscanf(" %dの"、&T)。 69個の インサート(根、T)。 70 } 71 のために(INTは iは= 0 ; I <M; ++ I) 72 { 73 INT T。 74 scanf関数(" %のD "、&T)。 75 INT M = クエリ(根、T)。 76 のprintf(" %dの\ n " 、M)。 77 } 78 デル(ルート)。 79 } 80 リターン 0 。 81 }