内郚怜玢のヒント









倜の郚屋。 暗闇の䞭で䜕千もの神秘的な顔が、モニタヌの青みがかった茝きに照らされおいたす。 100䞇個のキヌの耳障りなパチパチ音。 Enterキヌで機械のようなパンチを抌したす。 数十䞇匹のネズミの䞍吉な鳎き声 だから、確かに、負荷の高いシステムのすべおの開発者の想像力が発揮されたした。 そしお、あなたが圌を時間内に止めなければ、スリラヌ映画やホラヌ映画党䜓が出おくるかもしれたせん。 しかし、この蚘事では地面にずっず近づきたす。 怜玢ヒントの問題を解決するためのよく知られたアプロヌチ、それらを党文にする方法を孊んだ方法を簡単にレビュヌし、たたそれらにスピヌドを䞎えるために行ったいく぀かのトリックに぀いお話したすが、同時にリ゜ヌスぞの欲を教えたせん。 蚘事の最埌で、ボヌナスがあなたを埅っおいたす-小さな実䟋です。



「フヌドの䞋」にあるべきものは䜕ですか



  1. プロンプトの怜玢は党文である必芁がありたす。぀たり、プロンプトテキスト内の任意の順序でナヌザヌク゚リからすべおの単語を怜玢できる必芁がありたす。 たずえば、ナヌザヌがク゚リ「watch」を入力した堎合、デヌタベヌスには次のプロンプトが衚瀺されたす。







    「りォッチ」ずいう単語がこれらのプロンプトの異なる堎所にあるにもかかわらず、ナヌザヌは3぀すべおを芋る必芁がありたす。
  2. ナヌザヌの芁求は、キヌボヌドで入力䞭に完了しない堎合がありたす。 したがっお、単語ではなく接頭蟞で怜玢する必芁がありたす。 前の䟋では、「りォッチ」ずいう単語党䜓だけでなく、そのプレフィックス郚分に぀いおも3぀のヒントがすべお衚瀺されたす。 たずえば、「 watch 」。
  3. Search Mail.Ruは汎甚の怜玢゚ンゞンです。぀たり、可胜なク゚リの皮類は倚く、システムは数千䞇のヒントの䞭から怜玢できるはずです。
  4. 反応の速床は非垞に重芁なので、数ミリ秒で答えを出したいず思いたす。
  5. 最埌に、サヌビスは24時間365日皌働する信頌性の高いシステムでなければなりたせん。 ロシア党土およびCIS諞囜からのヒントは、毎秒数千のリク゚ストを凊理したす。 フォヌルトトレランスのために、したがっお、実装ずデバッグを容易にするために、非垞にシンプルで゚レガントな特定のアむデアをサヌビスの䞭心に持぀こずが非垞に望たしいです。


既知のアプロヌチ



1.プレフィックスの自動補完



a。 重み付きのヒント重み==人気は、ヒントに埓っお蟞曞順に゜ヌトされたす。

b。 ナヌザヌがク゚リプレフィックスを入力するず、バむナリ怜玢でヒントのサブセットが怜玢され、その先頭がこのプレフィックスを満たしたす。

c。 芋぀かったサブセットは重みの降順で゜ヌトされ、結果ずしお「最も重い」ヒントのトップがナヌザヌに提䟛されたす。











このアプロヌチの明らかな最適化は、 ツリヌのノヌドに重みを持぀パトリシアツリヌです。 最も「重い」ク゚リを遞択する堎合、原則ずしお、 優先床キュヌ 、たたは察数怜玢時間を提䟛するセグメントツリヌ が䜿甚されたす 。 必芁に応じお、 RMQアルゎリズムを介しおLCAを䜿甚しおサヌバヌのメモリを消費するこずができたす。そうするず、 非垞に迅速なプレフィックスヒントが埗られたす。 このアプロヌチには、速床、コンパクトさ、実装の容易さの3぀の利点がありたす。 ただし、明癜で最も䞍快な欠点は、プロンプトのテキスト内の単語の順列を怜玢できないこずです。 ぀たり、このようなプロンプトはプレフィックスのみであり、フルテキストではありたせん。



2.党文自動補完



a。 ヘルプテキストずナヌザヌリク゚ストは䞀連の単語ず芋なされたす。

b。 ナヌザヌがク゚リを入力するず、デヌタベヌスは、プロンプト内の䜍眮に関係なく、ナヌザヌのすべおの単語たたはプレフィックスを含むプロンプトのサブセットを怜玢したす。

c。 芋぀かったサブセットは、ヒントワヌドの降順でク゚リワヌドに゜ヌトされ、次に重みの降順で゜ヌトされ、「最も重い」もののTOPがナヌザヌに返されたす。











実際、これはフルテキストアプロヌチであり、これに぀いおはさらに説明したす。 このテヌマに関しおは、囜内倖の著者による膚倧な数の出版物がむンタヌネットで入手できたす。 䟋



ここで考慮されおいない䞊蚘およびその他のアプロヌチは、収益性+速床+シンプルさの組み合わせでは満足できたせんでした。 そのため、ニヌズを満たす独自のアルゎリズムを開発したした。



問題の正匏な声明



アルゎリズムを説明する前に、問題をより正匏な方法で定匏化したす。 だから、䞎えられた



必須です



玢匕



ヒントによる党文怜玢が必芁なため、むンデックスの基瀎は、䞀般的な党文怜玢の実装ぞの叀兞的なアプロヌチであり、最新のWeb怜玢゚ンゞンはこれに基づいおいたす。 党文怜玢は通垞、いわゆるドキュメント間で実行されたす。぀たり、ナヌザヌのリク゚ストから単語を怜玢するテキストです。 アルゎリズムの本質は、フォワヌドむンデックスずリバヌスむンデックスの2぀の単玔なデヌタ構造に瞮小されたす。





これら2぀のデヌタ構造を䜿甚するず、ナヌザヌの芁求を満たすすべおのドキュメントを簡単に芋぀けるこずができたす。 これを行うには、次のものが必芁です。

  1. 逆むンデックスク゚リの単語に埓っお、これらの単語が芋぀かったドキュメントのIDリストを芋぀けたす。 これらのリストの共通郚分は、ク゚リからのすべおの単語が芋぀かったidドキュメントの結果リストです。
  2. 盎接むンデックス受信したIDで゜ヌスドキュメントを芋぀け、ナヌザヌに「枡したす」。


この蚘事では説明が十分であるため、怜玢の詳现に぀いおは、スタンフォヌド倧孊の本「 情報怜玢の抂芁 」に送りたす。



叀兞的なアルゎリズムは単玔で優れおいたすが、ク゚リの単語は䞀般に「未完成」であるため、玔粋な圢匏ではヒントには適甚されたせん。 たたは、䞊で述べたように、リク゚ストは単語ではなくプレフィックスで構成されたす。 この問題を解決するために、逆むンデックスを完成させたした。これが埗られたものです。











泚 以䞋の図では、簡朔にするために、ツリヌのいく぀かのノヌドが耇数の文字の1぀の遷移に「マヌゞ」されおいたす。



䟋を䜿甚しおむンデックス怜玢を分析したしょう。

  1. 䞊蚘のむンデックスを自由に䜿甚でき、ナヌザヌがすでにリク゚ストの䞀郚を入力しおいるずしたす。 次の文字がキヌボヌドに入力されたしたが、䞍完党なリク゚スト「 omn​​ia v 」を受け取りたした。
  2. ク゚リをプレフィックスワヌドに分割したす。「 omn​​ia 」ず「 v 」を取埗したす。
  3. 怜玢゚ンゞンずの類掚により、最初に、䞎えられた接頭語が䞎えられるず、逆むンデックスでid idリストを芋぀けたす。 逆むンデックスは2぀の郚分で構成されおいるこずに泚意しおください。

    a。 プロンプトのテキストから「切断」した単語を含むプレフィックスツリヌ 「トラむ」、「ボロン」。

    b。 ツヌルチップIDのリスト-盎接むンデックス内のツヌルチップテキストのむンデックス。これに぀いおは以䞋で説明したす。 リストはidの昇順で゜ヌトされ、単語が終わる頂点に配眮されたす。

    私はトラむが私たちにずっお2぀の理由で良いず蚀わなければなりたせん

    • 時間Olognで任意の単語接頭蟞を芋぀けるために䜿甚できたす。ここで、 nは接頭蟞の長さです。
    • 特定のプレフィックスに぀いお、その継続のすべおのオプションを簡単に決定できたす。


    そのため、各接頭蟞に぀いお、ツリヌを䞋っお行き、䞭間ノヌドで自分自身を芋぀けたす。 次に、 正しい ID IDリストを取埗する必芁がありたす。
  4. すべおの子ノヌドのリストをマヌゞしたす。 䜕のために 通垞の怜玢゚ンゞンず同様に、各プレフィックスのIDリストを暪断する必芁がありたすが、2぀の「BUT」がありたす。

    a。 たず、すべおのノヌドにidヒントのリストが含たれおいるわけではなく、単語党䜓がダりンロヌドされるノヌドのみが含たれおいたす。

    b。 第二に、葉ノヌドを陀き、各ツリヌノヌドには特定の継続がありたす。 ぀たり、1぀のプレフィックスに察しお非垞に倚くの拡匵子が存圚する可胜性があり、これらの拡匵子を考慮する必芁がありたす。

    したがっお、抑制を芋぀ける前に、個々のプレフィックスごずにIDヒントのリストを「合蚈」する必芁がありたす。 したがっお、各接頭蟞に぀いお、この接頭蟞に埓っおツリヌ内で停止したノヌドから開始しお、ツリヌを再垰的に深く巡回し、マヌゞアルゎリズムによっおその子ノヌドのすべおのリストの結合を構築したす。 この図では、プレフィックスで停止したノヌドには赀い䞞が付けられ、 マヌゞ操䜜には 「 U 」 が付けられおいたす。
  5. 次に、各プレフィックスの合成ナニオンリストを暪断したす。 ゜ヌトされたリストを暪断するためのさたざたなアルゎリズムは単なる海であり、それぞれが異なるタむプのシヌケンスにより適しおいるず蚀わなければなりたせん。 最も効果的なものの1぀は、Ricardo Baez-YatesおよびAlejandro Salingerアルゎリズムです。 戊闘のヒントでは、特定のタスクを解決するのに最適な独自のアルゎリズムを䜿甚したすが、Baez-Yates-Salingerアルゎリズムはか぀お私たちにむンスピレヌションを䞎えたした。
  6. 芋぀かったIDによっお、ヒントテキストを探しおいたす。 この堎合の盎接むンデックスは、怜玢゚ンゞンの盎接むンデックスず同じです。぀たり、文字列の単玔な配列ベクトルです。 ヘルプテキストに加えお、远加情報を含めるこずができたす。 特に、ここでは人気の重みを保存したす。


そのため、6番目のステヌゞの終わりたでに、ナヌザヌリク゚ストからのすべおのプレフィックスがあるすべおのヒントが既にありたす。 明らかに、この段階で埗られるヒントの数は非垞に倚く、数千から数十䞇に及ぶ堎合があり、ナヌザヌに「プロンプト」を出すために必芁なのは最高のものだけです。 この問題は、別のアルゎリズムであるランキングアルゎリズムによっお解決されたす。



次に、絶察に䜕もせずにプロンプ​​トを「半分」ランク付けできるようにする1぀の小さなトリックを芋おいきたす。 そしお、2぀の問題を怜蚎する過皋で、これに぀いお以䞋で説明したす。



スピヌドアップ



「時期尚早の最適化はすべおの悪の根源です」-ドナルド・クヌヌトによっお策定された人気のあるプログラミングの知恵は述べおいたす。 しかし、䞊蚘のアルゎリズムを玔粋な圢で実装するず、2぀のパフォヌマンスの問題が発生したす。 したがっお、私たちにずっお、スピヌドを求める闘争の欠劂はさらに悪いこずです。



最初の問題は、リストのマヌゞが遅いこずです 。 この問題をさらに詳しく考えおみたしょう。

  1. 私たちのツリヌトレむには、文字「 a 」で始たる1000個の単語が既に存圚するずしたす実際には、さらに倚くの単語が存圚したす。





  2. 明らかに、1000ワヌドの堎合、idヒントの最小平均数も玄1000です。぀たり、平均しお、文字「a」で始たるワヌドがある最䜎1000のヒントがありたす。
  3. ここで、ナヌザヌがこの文字「 a 」で䜕かを怜玢するこずにしたず想像しおください。 アルゎリズムによれば、プレフィックス「a」に察しお、ノヌド「a」の䞋にあるすべおの子ノヌドのリストを結合する操䜜が開始されたす。 圓然、この操䜜には適切なリ゜ヌスが必芁です。たず、新しいリストにメモリを割り圓お、次に、この新しいリストにidをコピヌしたす。


結合は、2぀のトリックを䜿甚しお最適化できたす。



しかし、私たちの実隓では、ナニオンを䜿甚したトリックはキャッシングのために最適化ず比范できないこずが瀺されたした。 はい、はい、リヌフトップだけでなく、ツリヌの各ノヌドにヒントのIDを远加し始めたした。 合蚈マヌゞする必芁はありたせん-各可胜なプレフィックスの既補リストはツリヌノヌドに盎接ありたす。 そしお、逆むンデックスの圢匏は次のずおりです。











しかし、埅っおください ツリヌの各ノヌドにidのヒントを入れたすか ずおも無駄に芋えたすよね しかし、それはずおも無駄ですか 掚論



そこで、可胜なプレフィックスごずにすべおのリストをキャッシュするこずで、リストを結合する問題を解決したした。



2番目の問題は、リストの亀差が遅いこずず、重量によるチップのランキング゜ヌトです 。 アルゎリズムによるず、結合埌、2぀の重芁なステップが続き、それぞれにパフォヌマンスの問題がありたす。

  1. 結合リストの亀差。 倧芏暡なデヌタベヌスでは、特に短いプレフィックスの堎合、実際のリストは長すぎたす。 したがっお、「 a b 」のような短いク゚リのクロスリストは長すぎたす。
  2. たず、重量の降順でのランキングのヒント。 亀差点埌の最終リストも非垞に倧きくなる可胜性があるため、ク゚リ「 a b 」のように数千のidを゜ヌトするこずも採算が取れたせん。


結果を埗るために必芁なのは7〜10個の「最良の」ヒントだけであるこずを思い出しお、2぀のポむントで構成される非垞に簡単な゜リュヌションを芋぀けたした。

  1. IDヒントの正しい順序。 IDリストをコンパむルしお、りェむトが最倧のツヌルチップのIDが最小になるようにしたす。 ぀たり、ヒントは重みの降順でむンデックスに远加する必芁がありたす。 したがっお、亀差点の結果のリストは、重みずID倀を枛らすこずで既に同時に゜ヌトされたす。 このアプロヌチを「 事前ランキング 」ず呌びたす。
  2. 完党な亀差点は必芁ありたせん。 経隓的に確立されたした亀差点ではすべおを取るこずはできたせんが、最初のK個のチップK> Nであり、チップの目暙数Nに比䟋するを取るだけで十分であり、それらの䞭にはすでに重量によっお適切なものを遞択できるものがありたす単語順で。 たずえば、TOP N = 10の最高のヒントが必芁な堎合、最初のK = 100に぀いおの結果の亀差から遞択する必芁がありたす。これを行うには、亀差するずきに、結果リストにあるIDの数をカりントし、最初の100を入力するずすぐに停止したす亀差点。









したがっお、重量によるランキングず「怠“な」K最初のヒントぞの亀差の䞡方を最適化したした。



実装



最初に玄束したように、蚘事で説明されおいるアルゎリズムを実装するC ++の実甚䟋を投皿したす。 ゜ヌスデヌタベヌスずしお任意のテキストファむルを䜿甚できたす。各行はヒントです。 たずえば、 ラテン語  source のこずわざや翌のある衚珟でそれを埋めるこずができたす。そうすれば、ロシア語ぞの翻蚳やその逆の翻蚳をすばやく取埗できたす。







実装の機胜に぀いおは説明せず、読者に提䟛したす。利点は非垞に簡単です。



結論の代わりに残されたもの



もちろん、ここで玹介するアルゎリズムは最も䞀般的な圢匏で説明されおおり、倚くの質問はこの蚘事の範囲倖です。 ツヌルチップ開発者を考えるのに圹立぀他のものは䜕でしょう



それだけです ご枅聎ありがずうございたした。



アレクセむ・メドベチェク、

怜玢ヒント開発者 。



All Articles