Алгоритм с одним проходом для этой проблемы может быть следующим:
blockquote>
- Если строка пуста, возвращаем 1
- , пусть переходы = число соседних пар пар (c1, c2), где
c1 == ' '
иc2 != ' '
- , если предложение начинается с пробела, return
transitions
else returntransitions + 1
Вот пример со строкой = «Очень, очень, очень, очень, очень большая собака съела мою домашнюю работу !!!!»
i | 0123456789 c2 | A very, very, very, very, very big dog ate my homework!!!! c1 | A very, very, very, very, very big dog ate my homework!!!! | x x x x x x x x x x
Объяснение
Let `i` be the loop counter. When i=0: c1='A' and c2=' ', the condition `c1 == ' '` and `c2 != ' '` is not met When i=1: c1=' ' and c2='A', the condition is met ... and so on for the remaining characters
Этот алгоритм правильно обрабатывает случаи с несколькими пробелами
Вот два решения, которые я придумал с помощью
Наивное решение
size_t count_words_naive(const std::string_view& s) { if (s.size() == 0) return 0; size_t count = 0; bool isspace1, isspace2 = true; for (auto c : s) { isspace1 = std::exchange(isspace2, isspace(c)); count += (isspace1 && !isspace2); } return count; }
Если вы тщательно подумаете, сможет свести этот набор операций к внутреннему продукту, что было сделано ниже.
Внутреннее prod-решение
size_t count_words_using_inner_prod(const std::string_view& s) { if (s.size() == 0) return 0; auto starts_with_space = isspace(s.front()); auto num_transitions = std::inner_product( s.begin()+1, s.end(), s.begin(), 0, std::plus<>(), [](char c2, char c1) { return isspace(c1) && !isspace(c2); }); return num_transitions + !starts_with_space; }