4

オーダーが 10^12 程度の文字列の大規模なセットがあり、適切なデータ構造を選択して、文字列が提供されると、O(log(n)) のような整数値を取得して関連付けることができるようにする必要があります。または O(m) 時間、'n' は文字列のリストの長さ、'm' は各文字列の長さです。

それぞれの長さが「m」で、サイズが「q」のアルファベットでエンコードされた文字列のセットは、この長さのほぼすべての可能な文字列をカバーすると予想できます。たとえば、長さが m = 39 の 10^12 個のすべてが一意のバイナリ文字列があるとします。これは、この長さの可能なすべてのバイナリ文字列のセットの ~54% をカバーしたことを意味します。

そのため、衝突を回避する文字列の適切なハッシュ関数を見つけることに関心があります。私が使用できる良いものはありますか?n 個の文字列のセットにインデックスを付けるのにどれくらいの時間がかかりますか?

または、サフィックスツリーを使用する必要がありますか? Ukkonen のアルゴリズムが線形時間の構築を可能にしていることはわかっていますが、類似した文字列が多数ある場合、これによりスペースが節約されるのではないでしょうか?

4

3 に答える 3

1

非常に多数の文字列を考えると、いくつかの点に焦点を当てて選択する必要があります。

1. Are your indexing structures going to fit in memory?

ハッシュテーブルの場合、答えは明らかにそうではありません。したがって、アクセス時間は O(1) よりもはるかに遅くなります。それでも、必要なディスク アクセスは 1 つだけです (挿入プロセス全体は O(N) になります)。

b-treeについては、 b+tree (内部ノードのスペースを節約するため) と内部ノードが完全に占有されると仮定して、いくつかの理論計算を行いました。この分析では、メモリに収まりません。

  • 通常のディスク ページ サイズは 4096 バイトです。これは、1 つの B ツリー ノードのサイズです。
  • 文字列の平均サイズは 70 バイトです (小さいほど良い)。
  • 子ノードのアドレスは 4 バイトです。
  • 内部ノードは d 個のキーを保持し、d+1 個の子アドレスを持ちます:
    **4096B = 4*(d+1)+70*d <=> d = 4096/75 => d = 54 **

* #メモリ内の内部ノード -> #ディスク内のノードを残す -> #マッピングされた文字列*

0 個の内部ノード -> 1 個の葉ノード -> 53 個の文字列がマップさ
れる 1 個の内部ノード -> 54 個の葉ノードが使用される (それぞれ 53 個の葉を持つ) -> 532 個の文字列がマップさ
れる 1+54 個の内部ノード -> 542 個の葉ノードが使用される -> 533 個の文字列がマップさ
れる . ..
...+54⁵ 内部ノード -> 54⁶ 葉ノード = 537 文字列がマッピングされる

53⁷ > 10^12 , but 54⁵*4096 bytes > 1TB of memory

文字列が均一に分散されていない場合は、一般的なプレフィックスを調べることができます。このようにして、内部ノードがより多くの子にアドレス指定できるようになり、メモリを節約できます。BerkeleyDBにはそのオプションがあります。


2. What kind of access are you going to employ? Large or small number of reads?
If you have large number of reads, are they random or sequential?  
  • アクセスがシーケンシャルである場合でも、キャッシュされたノードを大量に使用し (ディスク アクセスを必要としない)、リーフがシーケンシャルにリンクされている (b+tree) ため、btree の利点が得られる可能性があります。これは、範囲クエリにも最適です (そうではないと思います)。アクセスが完全にランダムな場合、ハッシュテーブルは常に 1 つのディスク アクセスしか必要とせず、btree はディスクに格納されている各レベルのディスク アクセスを必要とするため、高速です。

  • 少数のアクセスを行う場合は、挿入が常に高速になるため、ハッシュテーブルを使用することをお勧めします。

  • 文字列の総数がわかっているので、それをハッシュテーブルに示すことができ、バケット スケール操作で時間を失うことはありません (これは、すべての要素が再ハッシュされることを意味します)。

注:あなたのukkonensサフィックス ツリーについて何かを見つけました。挿入は線形で、アクセスもシーケンシャルです。ただし、一部のGBでのみ使用されていることがわかりました。[ref1][ref2]、および[ref3]のサフィックス ツリー アルゴリズムに関するリファレンスを次に示します。

これが何らかの形で役立つことを願っています...

于 2012-10-24T01:18:06.643 に答える
0

...

ハイボブ、

端的に言えば、従来の HASH+BTREE アプローチは強力で超高速です。

1000 万または 100 億の文字列が上記の構造に格納されるかどうかは問題ではありません。MAX シークのしきい値は常に非常に低くなります。

10^12 = 1,000,000,000,000 が必要ですが、これは 1 兆です。驚いたことに、私の重い文字列コーパスでさえ 10 億の範囲にあります。

C での実装を確認してください: http://www.sanmayce.com/#Section13Level

そのため、衝突を回避する文字列の適切なハッシュ関数を見つけることに関心があります。私が使用できる良いものはありますか?

C での最速のハッシュ テーブル検索関数は次のとおりです。

http://www.sanmayce.com/Fastest_Hash/index.html#KT_torture3

強力な CRC32 8slice バリアント (Castagnoli と Koopman の両方) よりも 300 ~ 500% 高速ですが、同様の衝突が特徴です。

于 2012-10-22T15:43:37.657 に答える