それはプレフィックス問題が含まれているハンドル文字列にプレフィックスツリーの使用に来たときに問題の解決を磨き、その後、理解と実現プレフィックスツリーを追加し、ちょうどLeetcode208問題は練習の手として、プレフィックスツリーを達成することです。
原則
「辞書木、またそう、ソート、統計のために。プレフィックスツリー、トライ木、木、ハッシュツリーのバリエーションとして、典型的なアプリケーションを知られており、文字列の多くを保存します(ただし、文字列に限定されません)検索エンジンのシステムは、多くの場合、テキストの単語頻度統計のために使用されています。
その利点は、以下のとおりです。共通のプレフィックス文字列を使用すると、不要な文字列の比較、高効率のBi Haxiクエリツリーを最小限に抑え、クエリ時間を短縮します。"
三つの基本的なプロパティ
- 文字が含まれていないルートノードは、ルートノードを除く各ノードは一つだけの文字が含まれています。
- ルートノードからのすべての文字を結ぶ経路上のノードには、このノードに対応する文字列です。
- 各ノードの文字子ノード全て異なるが含まれています。
トライは、ツリー構造、ストレージスペースを節約するために共通のプレフィックス文字列を使用しての利点です。
図1に示されるトライ。
図1
次の単語を追加することにより、トライ検索のステップ:
1、ルートから検索を開始
図2は、あなたが単語の最初の文字を見つけ、そして手紙によると、検索に対応した道を継続する文字を選択したいました。
図3に示すように、下方に第二の文字に係る検索パスを継続に対応するキャラクタを選択するキャラクタへのパスの第二の層のノード。
単語検索した後、最後のノードが終端ノードである見つけることがあれば4、検索は、辞書単語ツリーが含まれていることを示し、例えば図1の固体ノードように、ダウンしています
それが見つかった場合、最後のノードは単語が単語を追加することにより、辞書ツリーにないことを示す、ターミナルノードではありません。単語が完成し、検索ではなく、後続のノードがなかった場合、および
また、それは単語が単語を追加することにより、辞書ツリーにないことを示しています。
例えば、以下に示すように、ワードすご腕トライ検索パスにおいて、第一のサブ空間26内の最初のノードが「L」の添字に対応する次の現在のノードを検索するかどうかを調べるためには(存在するASCIIコードであり、「」を減算しますGET添字)、検索が失敗には直接のリターンはありません。がある場合、そのノードは、「L」に設定反復に続いて、4文字の完了後すご腕を見つけ、「T」内のノードの滞在、かどうかを決定するために、この時間が必要されます終端ノード、別の単語のそれ以外の接頭辞。
各キーは、リーフまたは内部ノードにルートからトライパスを表します。私たちは、最初のキー文字でルートから始めます。キー文字対応するリンクを持つ現在のノードを確認してください。2つのケースがあります。
リンクがあります。私たちは、パスの後ろにリンクの次のノードに移動し、次のキーの文字を検索するために続けています。
リンクが存在しません。キー文字、および現在のノードがisEndとしてマークされている場合、それがtrueを返すことに注意してください。:そうでない場合は、次の2つの可能性、両方のリターン偽があり
、残りのキーの文字がありますが、キーを見つけることができない、トライ木キーのパスをたどることができませんでした。
いいえ文字キーを残りませんが、現在のノードがisEndとしてマークされていません。言い換えれば、別のキーでちょうどトライプレフィックスツリーする鍵を探します。
タイトル:トライ(接頭辞木)実装:
トライプレフィックスツリーか、まだトライ木データ構造は、共通の処理の文字列です。すべての単語「」〜「Z」の文字列が、トライ構造を実装することを想定し、以下の4つの主要な機能を含んでいます。
空のインサート(文字列の単語):、単語を追加、加算を繰り返すことができます。
一つだけを削除し、単語が複数回追加された場合、単語を削除します。(文字列の単語)削除のボイド
ブール検索(文字列の単語):辞書ツリー内のクエリ単語かどうか。
int型prefixNumber(文字列の前には):前の接頭辞の文字列内の単語の数を返します。
leetcode 208問題の説明:
あって、トライ(プレフィックスツリー)を実装 insert
、 search
および startsWith
これらの3つの操作。
例:
トライトライ= 新しいトライ(); trie.insert( "りんご" ); trie.search( "りんご"); // 返回真 trie.search( "アプリ")。// 返回偽 trie.startsWith( "アプリ")。// 返回真 trie.insert( "アプリ" )。 trie.search( "アプリ")。// 返回真
説明:
- あなたは、すべての入力が小文字が行われていることを前提として
a-z
構成しました。 - すべての入力が空の文字列であることを確認します。
実現
これは、プレフィックスツリーのノード、ノードレコードを通るパスのパスの数、増加が挿入され、場合削除減少、現在のノードを記録するための端はゼロターミネータないという、終端ノードでありますノード。次のインデックスのノードのTrieNodeアレイ素子は、タイトル入力ワードで指定されているので、長さ26の配列を作成し、AZを小文字。
1 クラスTrieNode { 2 のint 経路; 3 int型END; 4 TrieNode []地図; 5 。6 TrieNode(){ 7。 パス= 0 ; 8 エンド= 0 ; 9 // 文字のためには、AZ、空間26の初期割り当ての長さそう 10 =地図新しい新しい TrieNodeを[26である]; 11 } 12です }
以下は、トライ動作の実装で、基本的なプロセスは、その後、「」のASCIIコードに応じチャー、チャーアレイ横断順序、及び差の配列に変換し、文字インデックスを取得、入力ワードが空であるか否かを判断することですノードは、その後、別のノードを見つけるために、再帰的に、現在のノードに割り当てられています。
パブリック クラストライ{ プライベートTrieNodeルート; パブリックトライ(){ ルート = 新しいTrieNode()。 } 公共 ボイド挿入(文字列の単語){ 場合(ワード== NULL ){ リターン。 } のchar [] CHS = word.toCharArray()。 TrieNodeノード = ルート。 node.path ++ ; int型のインデックス= 0 ; 以下のために(int型私は= 0; I <chs.length; I ++ ){ インデックスCHS = [I] - [A ' ; IF(node.map [インデックス] == NULL ){ node.map [インデックス] = 新しい新しいTrieNode(); } ノード = node.map [インデックス]; node.path ++ ; } // で決定するための文字列フォーカスサーチの最後のノードを表す ++ node.end ; } // 単語を削除し、単語が複数回追加された場合、削除つのみ。 公共 ボイド削除(文字列ワード){ IF (検索(ワード)){ 文字 [] = CHS word.toCharArray()。 TrieNodeノード = ルート。 int型のインデックス= 0 ; node.path - ; 以下のために(INT I 0 =; I <chs.length; I ++ ){ インデックス = CHS [I] - '' ; node.map [インデックス] .path - 。 ノード = node.map [インデックス]。 } node.end - 。 } } パブリック ブール検索(文字列の単語){ 場合(ワード== NULL ){ リターン 偽; } チャー [] CHS = word.toCharArray()。 TrieNodeノード = ルート。 int型のインデックス= 0 ; 以下のために(INT I 0 =; I <chs.length; I ++ ){ インデックス = CHS [I] - '' ; もし(node.map [インデックス] == NULL ){ 戻り 偽。 } 他{ ノード = node.map [インデックス]。 } } // もし(node.end!= 0){ // trueを返します。 // }他{ // falseに復帰; // } 戻り node.end = 0!; } / ** 戻る単語の数は、接頭文字列事前* / 公共 int型prefixNumber(文字列を事前){ IF(事前== nullの){ リターンを 0 ; } のchar [] = CHS pre.toCharArray(); TrieNodeノード = ルート; INTインデックス= 0 ; のための(INT I = 0; I <chs.length; I ++ ){ インデックス = CHS [I]は- 'A' ; IF(node.map [インデックス] == NULL ){ 戻り 0 ; } ノード = node.map [インデックス]; } 戻りnode.path; } / **は木か否かを判断しますこの接頭語文字列が存在する* / パブリック ブールのstartsWith(文字列のプレフィックス){ IF(接頭== NULL ){ リターン falseに; } のchar [] = CHS prefix.toCharArray(); TrieNodeノード = ルート; int型のインデックス= 0 ; のため(INTは I 0 =; I <chs.length; I ++ ){ インデックス = CHS [I] - '' ; もし(node.map [インデックス] == NULL ){ 戻り 偽。 } ノード = node.map [インデックス]。 }
//はtrueを返します。 リターン node.path = 0!; } }
参考:
[1] https://www.cnblogs.com/hengzhezou/p/11046886.html トライ(トライ木)実施
[2] https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/shi-xian-trie-qian-zhui-shu-by-leetcode/ leetcode 208の公式の説明