#include #include #include #include #include #include #include #include using namespace std; const int MAX_RESULT_DOCUMENT_COUNT = 5; enum class DocumentStatus { ACTUAL, IRRELEVANT, BANNED, REMOVED }; string ReadLine() { string s; getline(cin, s); return s; } int ReadLineWithNumber() { int result; cin >> result; ReadLine(); return result; } vector SplitIntoWords(const string& text) { vector words; string word; for (const char c : text) { if (c == ' ') { words.push_back(word); word = ""; } else { word += c; } } words.push_back(word); return words; } struct Document { int id; double relevance; int rating; }; class SearchServer { public: void SetStopWords(const string& text) { for (const string& word : SplitIntoWords(text)) { stop_words_.insert(word); } } void AddDocument(int document_id, const string& document, DocumentStatus status, const vector& ratings) { const vector words = SplitIntoWordsNoStop(document); const double inv_word_count = 1.0 / words.size(); for (const string& word : words) { word_to_document_freqs_[word][document_id] += inv_word_count; } rating_and_status_.emplace(document_id, RatingAndStatusHelper{ComputeAverageRating(ratings), status}); } vector FindTopDocuments(const string& raw_query, DocumentStatus status) const { vector matched_documents; const Query query = ParseQuery(raw_query); auto matched_documents_query = FindAllDocuments(query); for (const auto& document : matched_documents_query) { int id = document.id; if (rating_and_status_.at(id).status == status) { matched_documents.push_back({document.id, document.relevance, document.rating}); } } sort(matched_documents.begin(), matched_documents.end(), [](const Document& lhs, const Document& rhs) { return lhs.relevance > rhs.relevance; }); if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) { matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT); } return matched_documents; } private: struct RatingAndStatusHelper{ int rating; DocumentStatus status; }; set stop_words_; map> word_to_document_freqs_; map rating_and_status_; bool IsStopWord(const string& word) const { return stop_words_.count(word) > 0; } vector SplitIntoWordsNoStop(const string& text) const { vector words; for (const string& word : SplitIntoWords(text)) { if (!IsStopWord(word)) { words.push_back(word); } } return words; } static int ComputeAverageRating(const vector& ratings) { int rating_sum = 0; for (const int rating : ratings) { rating_sum += rating; } return rating_sum / static_cast(ratings.size()); } struct QueryWord { string data; bool is_minus; bool is_stop; }; QueryWord ParseQueryWord(string text) const { bool is_minus = false; // Word shouldn't be empty if (text[0] == '-') { is_minus = true; text = text.substr(1); } return { text, is_minus, IsStopWord(text) }; } struct Query { set plus_words; set minus_words; }; Query ParseQuery(const string& text) const { Query query; for (const string& word : SplitIntoWords(text)) { const QueryWord query_word = ParseQueryWord(word); if (!query_word.is_stop) { if (query_word.is_minus) { query.minus_words.insert(query_word.data); } else { query.plus_words.insert(query_word.data); } } } return query; } // Existence required double ComputeWordInverseDocumentFreq(const string& word) const { return log(rating_and_status_.size() * 1.0 / word_to_document_freqs_.at(word).size()); } vector FindAllDocuments(const Query& query) const { map document_to_relevance; for (const string& word : query.plus_words) { if (word_to_document_freqs_.count(word) == 0) { continue; } const double inverse_document_freq = ComputeWordInverseDocumentFreq(word); for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) { document_to_relevance[document_id] += term_freq * inverse_document_freq; } } for (const string& word : query.minus_words) { if (word_to_document_freqs_.count(word) == 0) { continue; } for (const auto [document_id, _] : word_to_document_freqs_.at(word)) { document_to_relevance.erase(document_id); } } vector matched_documents; for (const auto [document_id, relevance] : document_to_relevance) { matched_documents.push_back({ document_id, relevance, rating_and_status_.at(document_id).rating }); } return matched_documents; } }; /*SearchServer CreateSearchServer() { SearchServer search_server; search_server.SetStopWords(ReadLine()); const int document_count = ReadLineWithNumber(); for (int document_id = 0; document_id < document_count; ++document_id) { const string document = ReadLine(); int ratings_size; cin >> ratings_size; // создали вектор размера ratings_size из нулей vector ratings(ratings_size, 0); // считали каждый элемент с помощью ссылки for (int& rating : ratings) { cin >> rating; } search_server.AddDocument(document_id, document, ratings); ReadLine(); } return search_server; } int main() { const SearchServer search_server = CreateSearchServer(); const string query = ReadLine(); for (const Document& document : search_server.FindTopDocuments(query)) { cout << "{ " << "document_id = " << document.id << ", " << "relevance = " << document.relevance << ", " << "rating = " << document.rating << " }" << endl; } }*/ void PrintDocument(const Document& document) { cout << "{ "s << "document_id = "s << document.id << ", "s << "relevance = "s << document.relevance << ", "s << "rating = "s << document.rating << " }"s << endl; } int main() { SearchServer search_server; search_server.SetStopWords("и в на"s); search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, {8, -3}); search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, {7, 2, 7}); search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, {5, -12, 2, 1}); search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, {9}); cout << "ACTUAL:"s << endl; for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::ACTUAL)) { PrintDocument(document); } cout << "BANNED:"s << endl; for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::BANNED)) { PrintDocument(document); } return 0; }