fork download
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <map>
  5. #include <set>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9.  
  10. using namespace std;
  11.  
  12.  
  13. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  14.  
  15. string ReadLine() {
  16. string s;
  17. getline(cin, s);
  18. return s;
  19. }
  20.  
  21. int ReadLineWithNumber() {
  22. int result;
  23. cin >> result;
  24. ReadLine();
  25. return result;
  26. }
  27.  
  28. vector<string> SplitIntoWords(const string& text) {
  29. vector<string> words;
  30. string word;
  31. for (const char c : text) {
  32. if (c == ' ') {
  33. words.push_back(word);
  34. word = "";
  35. } else {
  36. word += c;
  37. }
  38. }
  39. words.push_back(word);
  40.  
  41. return words;
  42. }
  43.  
  44. struct Document {
  45. int id;
  46. double relevance;
  47. int rating;
  48. };
  49.  
  50. /*int ComputeAverageRating(const vector<int>& ratings) {
  51.   if (ratings.empty()) {
  52.   return 0;
  53.   }
  54.   int rating_sum = 0;
  55.   for (const int rating : ratings) {
  56.   rating_sum += rating;
  57.   }
  58.   // static_cast позволяет привести значение к типу int
  59.   // без использования дополнительной переменной
  60.   return rating_sum / static_cast<int>(ratings.size());
  61. }*/
  62.  
  63. class SearchServer {
  64. public:
  65. void SetStopWords(const string& text) {
  66. for (const string& word : SplitIntoWords(text)) {
  67. stop_words_.insert(word);
  68. }
  69. }
  70.  
  71. void AddDocument(int document_id, const string& document, const vector<int>& ratings) {
  72. const vector<string> words = SplitIntoWordsNoStop(document);
  73. const double inv_word_count = 1.0 / words.size();
  74. for (const string& word : words) {
  75. word_to_document_freqs_[word][document_id] += inv_word_count;
  76. }
  77. document_ratings_.emplace(document_id, ComputeAverageRating(ratings));
  78. }
  79.  
  80. vector<Document> FindTopDocuments(const string& raw_query) const {
  81. const Query query = ParseQuery(raw_query);
  82. auto matched_documents = FindAllDocuments(query);
  83.  
  84. sort(matched_documents.begin(), matched_documents.end(),
  85. [](const Document& lhs, const Document& rhs) {
  86. return lhs.relevance > rhs.relevance;
  87. });
  88. if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  89. matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  90. }
  91. return matched_documents;
  92. }
  93.  
  94. private:
  95. set<string> stop_words_;
  96. map<string, map<int, double>> word_to_document_freqs_;
  97. map<int, int> document_ratings_;
  98.  
  99.  
  100. static int ComputeAverageRating(const vector<int>& ratings) {
  101. if (ratings.empty()) {
  102. return 0;
  103. }
  104. int rating_sum = 0;
  105. for (const int rating : ratings) {
  106. rating_sum += rating;
  107. }
  108. // static_cast позволяет привести значение к типу int
  109. // без использования дополнительной переменной
  110. return rating_sum / static_cast<int>(ratings.size());
  111. }
  112.  
  113.  
  114. bool IsStopWord(const string& word) const {
  115. return stop_words_.count(word) > 0;
  116. }
  117.  
  118. vector<string> SplitIntoWordsNoStop(const string& text) const {
  119. vector<string> words;
  120. for (const string& word : SplitIntoWords(text)) {
  121. if (!IsStopWord(word)) {
  122. words.push_back(word);
  123. }
  124. }
  125. return words;
  126. }
  127.  
  128. struct QueryWord {
  129. string data;
  130. bool is_minus;
  131. bool is_stop;
  132. };
  133.  
  134. QueryWord ParseQueryWord(string text) const {
  135. bool is_minus = false;
  136. // Word shouldn't be empty
  137. if (text[0] == '-') {
  138. is_minus = true;
  139. text = text.substr(1);
  140. }
  141. return {
  142. text,
  143. is_minus,
  144. IsStopWord(text)
  145. };
  146. }
  147.  
  148. struct Query {
  149. set<string> plus_words;
  150. set<string> minus_words;
  151. };
  152.  
  153. Query ParseQuery(const string& text) const {
  154. Query query;
  155. for (const string& word : SplitIntoWords(text)) {
  156. const QueryWord query_word = ParseQueryWord(word);
  157. if (!query_word.is_stop) {
  158. if (query_word.is_minus) {
  159. query.minus_words.insert(query_word.data);
  160. } else {
  161. query.plus_words.insert(query_word.data);
  162. }
  163. }
  164. }
  165. return query;
  166. }
  167.  
  168. // Existence required
  169. double ComputeWordInverseDocumentFreq(const string& word) const {
  170. return log(document_ratings_.size() * 1.0 / word_to_document_freqs_.at(word).size());
  171. }
  172.  
  173. vector<Document> FindAllDocuments(const Query& query) const {
  174. map<int, double> document_to_relevance;
  175. for (const string& word : query.plus_words) {
  176. if (word_to_document_freqs_.count(word) == 0) {
  177. continue;
  178. }
  179. const double inverse_document_freq = ComputeWordInverseDocumentFreq(word);
  180. for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) {
  181. document_to_relevance[document_id] += term_freq * inverse_document_freq;
  182. }
  183. }
  184.  
  185. for (const string& word : query.minus_words) {
  186. if (word_to_document_freqs_.count(word) == 0) {
  187. continue;
  188. }
  189. for (const auto [document_id, _] : word_to_document_freqs_.at(word)) {
  190. document_to_relevance.erase(document_id);
  191. }
  192. }
  193.  
  194. vector<Document> matched_documents;
  195. for (const auto [document_id, relevance] : document_to_relevance) {
  196. matched_documents.push_back({
  197. document_id,
  198. relevance,
  199. document_ratings_.at(document_id)
  200. });
  201. }
  202. return matched_documents;
  203. }
  204. };
  205.  
  206.  
  207. SearchServer CreateSearchServer() {
  208. SearchServer search_server;
  209. search_server.SetStopWords(ReadLine());
  210.  
  211. const int document_count = ReadLineWithNumber();
  212. for (int document_id = 0; document_id < document_count; ++document_id) {
  213. const string document = ReadLine();
  214. int ratings_size;
  215. cin >> ratings_size;
  216.  
  217. // создали вектор размера ratings_size из нулей
  218. vector<int> ratings(ratings_size, 0);
  219.  
  220. // считали каждый элемент с помощью ссылки
  221. for (int& rating : ratings) {
  222. cin >> rating;
  223. }
  224.  
  225. search_server.AddDocument(document_id, document, ratings);
  226. ReadLine();
  227. }
  228.  
  229. return search_server;
  230. }
  231.  
  232.  
  233. int main() {
  234. const SearchServer search_server = CreateSearchServer();
  235.  
  236. const string query = ReadLine();
  237. for (const Document& document : search_server.FindTopDocuments(query)) {
  238. cout << "{ "
  239. << "document_id = " << document.id << ", "
  240. << "relevance = " << document.relevance << ", "
  241. << "rating = " << document.rating
  242. << " }" << endl;
  243. }
  244. return 0;
  245. }
Success #stdin #stdout 0s 5704KB
stdin
и в на
3
белый кот и модный ошейник
2 8 -3
пушистый кот пушистый хвост
3 7 2 7
ухоженный пёс выразительные глаза
4 5 -12 2 1
пушистый ухоженный кот 
stdout
{ document_id = 1, relevance = 0.650672, rating = 5 }
{ document_id = 2, relevance = 0.274653, rating = -1 }
{ document_id = 0, relevance = 0.101366, rating = 2 }