わかりました、それで私は馬鹿のように聞こえません私は問題/要件をより明確に述べるつもりです:
- Needle(パターン)とhaystack(検索するテキスト)はどちらもCスタイルのヌル終了文字列です。長さ情報は提供されません。必要に応じて、計算する必要があります。
- 関数は、最初の一致へのポインタを返す
NULL
か、一致が見つからない場合に返す必要があります。 - 失敗した場合は許可されません。これは、非定数(または大きな定数)のストレージ要件を持つアルゴリズムでは、割り当ての失敗に対するフォールバックケースが必要になることを意味します(フォールバックケアのパフォーマンスは、最悪の場合のパフォーマンスに影響します)。
- 実装はCで行う必要がありますが、コードなしでアルゴリズム(またはそのようなものへのリンク)を適切に記述してもかまいません。
...そして「最速」とはどういう意味か:
- 決定論的な
O(n)
場所n
=干し草の長さ。(しかしO(nm)
、より堅牢なアルゴリズムと組み合わせて確定的なO(n)
結果を得る場合、通常はローリングハッシュなどのアルゴリズムからのアイデアを使用することが可能です)。 if (!needle[1])
特に最も一般的なケースである可能性が高い非常に短い針では、素朴なブルートフォースアルゴリズムよりもパフォーマンスが低下する(ある程度測定できる;数クロックなどで問題ない)。(無条件に重い前処理のオーバーヘッドは悪く、針の可能性を犠牲にして病理学的針の線形係数を改善しようとしています。)- 任意の針と干し草を考えると、他の広く実装されているアルゴリズムと比較して、同等またはそれ以上のパフォーマンス(検索時間が50%以上長くなります)。
- これらの条件は別として、私は「最速」の定義をオープンエンドのままにしておきます。良い答えは、「最速」を提案しているアプローチを検討する理由を説明する必要があります。
私の現在の実装は、glibcのTwo-Wayの実装よりも(入力に応じて)約10%遅く、8倍速く実行されます。
更新:現在の最適なアルゴリズムは次のとおりです。
- 長さが1の針には、を使用します
strchr
。 - 長さが2〜4の針の場合、マシンワードを使用して、次のように2〜4バイトを一度に比較します。16ビットまたは32ビットの整数に針をビットシフトでプリロードし、各反復で干し草の山から古いバイトアウト/新しいバイトを循環させます。 。干し草の各バイトは1回だけ読み取られ、0(文字列の終わり)に対するチェックと1つの16ビットまたは32ビットの比較が行われます。
- 長さが4より大きい針の場合は、ウィンドウの最後のバイトにのみ適用される不良なシフトテーブル(Boyer-Mooreなど)を使用した双方向アルゴリズムを使用します。1 kbテーブルを初期化するオーバーヘッド(多くの中程度の長さの針の正味の損失になる)を回避するために、シフトテーブルのどのエントリが初期化されるかを示すビット配列(32バイト)を保持します。未設定のビットは、針に表示されることのないバイト値に対応します。針の全長シフトが可能です。
私の頭に残っている大きな質問は次のとおりです。
- 悪いシフトテーブルをより有効に活用する方法はありますか?Boyer-Mooreは、逆方向(右から左)にスキャンすることでそれを最大限に活用しますが、双方向には左から右へのスキャンが必要です。
- 一般的なケース(メモリ不足や2次のパフォーマンス条件はない)で見つかった実行可能な候補アルゴリズムは、順序付きアルファベットでの双方向および文字列マッチングの2つだけです。しかし、異なるアルゴリズムが最適である、簡単に検出できるケースはありますか?確かに、
O(m)
(m
針の長さである)空間アルゴリズムの多くは、m<100
そのために使用できます。線形時間のみを必要とする可能性がある針の簡単なテストがある場合は、最悪の2次アルゴリズムであるアルゴリズムを使用することもできます。
ボーナスポイント:
- 針と干し草の両方が整形式のUTF-8であると想定して、パフォーマンスを向上させることができますか?(バイト長が異なる文字では、整形式であることにより、needleとhaystackの間に文字列の整列要件が課せられ、不一致のヘッドバイトが検出されたときに自動的に2-4バイトのシフトが可能になります。最大の接尾辞の計算、適切な接尾辞のシフトなどにより、すでにさまざまなアルゴリズムが提供されていますか?)
注:私はそこにあるほとんどのアルゴリズムをよく知っていますが、実際のパフォーマンスはそうではありません。ここに良い参照がありますので、人々は私にコメント/回答としてアルゴリズムに関する参照を与え続けません:http : //www-igm.univ-mlv.fr/~lecroq/string/index.html
strstr
を後で何かに残したので、私は実際にあなたがリンクした論文を適切に読むために移動していませんが、それは非常に有望に聞こえます。返信がないことをお詫び申し上げます。