Найти, если строка содержит символ в С++ (повышение разрешено)

Предположим, что у меня есть строка, и я хочу найти, присутствует ли конкретный символ (например, '|') или нет, что является лучшим и самым быстрым способом для этого? Я знаю, что строка find реализует. Я прошу еще более быстрой реализации, чем эта.

Ответ 1

Используйте std::string::find

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

Там вряд ли будет что-то более эффективное. O (n) - лучшее, что вы можете сделать. Стандартная реализация библиотеки должна быть практически оптимальной.

Ответ 2

Другой способ - использовать функцию strchr в соответствующей строке c_str:

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

Не уверен, как он сравнивается с поиском std с точки зрения скорости, хотя...

Позиция найденного символа

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

Ответ 3

Добавление ответа Тома Таннера. Если вы не хотите делать какие-либо априорные вычисления, вы будете застревать в O (n), т.е. Существует линейная корреляция между длиной строки, которую вы ищете, и потреблением времени. Том предложил создать массив (или вектор) логических элементов, указывающий на наличие определенного символа. Для индексирования строки потребуется O (n) один раз, но тогда вы можете проверить любое количество символов в O (1) (постоянное время), если оно включено. Недостатком такого подхода является то, что вам понадобится много памяти (после того, как вы решите, что вам нужно поддерживать unicode).

В качестве компромисса вы можете использовать std:: set или подобное, сохраняя только символы, которые действительно существуют в вашей строке ввода. Потребление памяти тогда будет примерно линейным относительно количества различных символов в строке, но поиск будет равен O (log n), то есть логарифмическому по времени.

Конечно, вы должны измерить/профиль, а затем объясните, какой вариант использования вы фактически оптимизируете. Пока вы этого не сделаете, придерживайтесь того, что проще всего понять и прочитать.

Ответ 4

Из этот источник эмпирический тест, выполненный с помощью Visual Studio 2013 Компилятор показывает, что strchr работает примерно 2x быстрее, чем std::string:: find.

Ответ 5

Существует только один способ сделать это. Просто перебирайте строку, чтобы проверить, существует ли персонаж, которого вы ищете. Вы можете сделать это, используя функцию string::find, которая получает символ и возвращает первую позицию, которая встречается в строке, или string::npos, если это значение отсутствует. Вы также можете использовать std::find, который получает два итератора, begin и end и значение ключа 'k' и возвращает итератор, указывающий на первое вхождение k в диапазоне [begin, end] или end, если k не найден. И, конечно, вы можете реализовать функцию find самостоятельно, например:

string::size_type pos=string::npos;
for(string::size_type i=0; i<s.size(); ++i) {
  if(s[i] == key) {
     pos=i;
     break;
  }
}
if(pos != string::npos) {
  // key was found
} else {
  // not found
}

или это:

string::iterator pos=s.end();
for(string::iterator i=s.begin(); i!=s.end(); ++i) {
  if(*i == key) {
    pos=i;
    break;
  }
}
if(pos != s.end()) {
  // found
} else {
  // not found
}

Подробнее о std::string::find и std::find:

Ответ 6

Учитывая ваше утверждение о том, что вы хотите что-то быстрее, чем string:: find, единственное, о чем я могу думать, это создать класс, который имел высоко настраиваемые операторы присваивания, которые при каждом обновлении строки обновляли внутреннюю таблицу, содержащую первая позиция в строке любого возможного символа (256 для строки char, 65536 (?) для широкой строки). Это имеет O (1) поиск за счет довольно большой сложности, добавленной к неконстантным операциям.

Ответ 7

Вы можете попробовать следующее:

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