web-dev-qa-db-ja.com

文字列にC ++の文字が含まれているかどうかを確認します(ブーストが許可されます)

文字列があり、特定の文字(「|」など)が存在するかどうかを確認したい場合、これを行うための最良かつ最速のテクニックは何ですか?文字列検索の実装を知っていますが、これよりもさらに高速な実装を求めています。

15
psyche

使用する - std::string::find

if (str.find('|') != std::string::npos)
{
    // ...
}

より効率的なものはほとんどありません。 O(n)が最善です。標準ライブラリの実装は、ほぼ最適です。

32
Fred Larson

このソース Visual Studio 2013コンパイラで行われた実証テストでは、strchrルーチンが約2倍高速であることが示されています thanstd :: string :: findの実装。

2
Mouze

別の方法は、対応するc_str文字列でstrchr関数を使用することです。

if(strchr(str.c_str(), '|'))
{
    \\found
}

しかし、速度の点でstd findと比較する方法がわかりません...

見つかったキャラクターの位置は

size_t pos = strchr(str.c_str(),'|') - str.c_str();
1
afakih

トム・タナーの答えを付け加えます。先験的な計算を行いたくない場合は、O(n)で止まってしまいます。つまり、検索している文字列の長さと消費時間の間に線形相関があります。トムは、特定の文字が発生したかどうかを示すブール値の配列(またはベクトル)をセットアップすることを提案しました。文字列にインデックスを付けるためにO(n)を1回必要としますが、その後、O(1)(一定時間)このアプローチの欠点は、大量のメモリが必要になることです(ユニコードをサポートする必要があると判断した場合)。

妥協案として、std :: setなどを使用して、入力文字列に実際に存在する文字のみを保存できます。その場合、メモリ消費は文字列内の異なる文字数に関してほぼ線形になりますが、ルックアップはO(log n)、つまり時間的に対数になります。

もちろん、測定/プロファイルを作成してから、実際に最適化するユースケースをここで説明する必要があります。そうするまで、最も理解しやすく、読みやすいものに固執してください。

1

これを試すことができます:

   string s1 = "Hello";
   string s2 = "el";
   if(strstr(s1.c_str(),s2.c_str()))
   {
    cout << " S1 Contains S2";
   }
0
HappyTran

String :: findよりも高速なものが必要であるというステートメントを考えると、私が考えることができる唯一のことは、文字列の更新ごとに、可能なすべての文字の文字列(char文字列の場合は256、ワイド文字列の場合は65536(?))。これにはO(1)ルックアップがありますが、非const操作に非常に多くの複雑さが追加されます。

0
Tom Tanner