Advertisement
giGii

худшее решение

Dec 19th, 2022
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.72 KB | None | 0 0
  1. SearchServer::PlusMinusWords SearchServer::ParseQuery(const std::string& raw_query) const {
  2.  
  3.     SearchServer::PlusMinusWords query_words;
  4.  
  5.     ThrowSpecialSymbolInText(raw_query);
  6.  
  7.     // это нужно, чтобы и плюс-, и минус-слова в своих векторах были уже отсортированы, потому что далее их ждет unique-erase
  8.     std::vector<std::string> sorted_query_words = SplitIntoWordsNoStop(raw_query); // вот это гарантировало бы, что минус-слова попадут в контейнер с минус-словами раньше, и можно было бы проверять, когда добавляешь плюс-слово, что оно не находится в минус-словах; но тут уже другое -- если слово есть и с минусом и без минуса, я кем его должен считать?
  9.     // остается просто забить за вероятность, что минус слово окажется и плюс словом
  10.  
  11.     std::sort(std::execution::par,
  12.               sorted_query_words.begin(), sorted_query_words.end());
  13.  
  14.     for (const std::string& word : sorted_query_words) {
  15.         if (word[0] == '-') {
  16.             auto minus_word = word.substr(1);
  17.            
  18.             if (minus_word.empty() || minus_word[0] == '-') {
  19.                 throw std::invalid_argument("Alone or double minus in query"s);
  20.             }
  21.  
  22.             query_words.minus_words.push_back(minus_word);
  23.  
  24.         } else { /* else if (query_words.minus_words.count(word) == 0) // было тут вместо else, чтобы защитить плюс-слова от проникновения минус-слова, которое подано в запросе без минуса (запрос же автоматически генерируется) */
  25.             query_words.plus_words.push_back(word);
  26.         }
  27.     }
  28.  
  29.     std::vector<std::string>::iterator last;
  30.  
  31.     // чистим минус-слова от дубликатов
  32.     last = std::unique(query_words.minus_words.begin(), query_words.minus_words.end());
  33.     query_words.minus_words.erase(last, query_words.minus_words.end());
  34.  
  35.     // чистим плюс-слова от дубликатов
  36.     last = std::unique(query_words.plus_words.begin(), query_words.plus_words.end());
  37.     query_words.plus_words.erase(last, query_words.plus_words.end());
  38.  
  39.     return query_words;
  40. }
  41. // ===========================================================================================================================
  42. std::tuple<std::vector<std::string>, DocumentStatus> SearchServer::MatchDocument(std::execution::parallel_policy, const std::string& raw_query, int document_id) const {
  43.  
  44.     if (IsNegativeDocumentId(document_id)) {
  45.         throw std::invalid_argument("Negative document id"s);
  46.     }
  47.  
  48.     if (IsNonexistentDocumentId(document_id)) {
  49.         throw std::invalid_argument("Nonexistent document id"s);
  50.     }
  51.  
  52.     // тут два отсортированных вектора с уникальными + и - словами
  53.     SearchServer::PlusMinusWords prepared_query = ParseQuery(raw_query);
  54.  
  55.     // вытягиваю слова документа из сервера, других вариантов кроме как по map пройтись у меня нет
  56.     std::vector<const std::string*> words(TF_by_id_.at(document_id).size());
  57.     std::transform(std::execution::par,
  58.                    TF_by_id_.at(document_id).begin(), TF_by_id_.at(document_id).end(),
  59.                    words.begin(),
  60.                    [](auto& item) { return &item.first; });
  61.  
  62.     bool is_minus_words_in_document = any_of(std::execution::par, words.begin(), words.end(),
  63.                                              [&prepared_query](const std::string* word) {
  64.  
  65.                                                 return count(std::execution::par, // у меня же теперь вектор! запускаю параллельный ЛИНЕЙНЫЙ поиск (а был set, где поиск шел за log)
  66.                                                              prepared_query.minus_words.begin(),
  67.                                                              prepared_query.minus_words.end(),
  68.                                                              *word);
  69.                                              }
  70.                                             );
  71.  
  72.     if (is_minus_words_in_document) {
  73.         return {std::vector<std::string>{}, document_info_.at(document_id).status};
  74.     }
  75.  
  76.     std::vector<const std::string*> result_intersection_ptrs(std::min(prepared_query.plus_words.size(), words.size()));
  77.     std::copy_if(std::execution::par, words.begin(), words.end(),
  78.                  result_intersection_ptrs.begin(),
  79.                  [&prepared_query](const std::string* word) {
  80.  
  81.                     return count(std::execution::par,
  82.                                  prepared_query.plus_words.begin(),
  83.                                  prepared_query.plus_words.end(),
  84.                                  *word);
  85.                  }
  86.                 );
  87.    
  88.     std::vector<std::string> result_intersection(result_intersection_ptrs.size());
  89.     std::transform(std::execution::par,
  90.                    result_intersection_ptrs.begin(), result_intersection_ptrs.end(),
  91.                    result_intersection.begin(),
  92.                    [](const std::string* word) { return word != nullptr ? *word : ""s; });
  93.    
  94.     std::sort(std::execution::par,
  95.               result_intersection.begin(), result_intersection.end());
  96.    
  97.     // найдем первое не пустое слово
  98.     auto start = std::upper_bound(result_intersection.begin(), result_intersection.end(), ""s);
  99.  
  100.     // вариант 1: ratio 1.55
  101.     std::vector<std::string> result;
  102.     std::move(start, result_intersection.end(), std::back_inserter(result));
  103.     return {result, document_info_.at(document_id).status};
  104.  
  105.     // // вариант 2: ratio 1.66
  106.     // return {{start, result_intersection.end()}, document_info_.at(document_id).status};
  107.  
  108.     // // вариант 3: неправильный результат
  109.     // // Решение упало. Assertion failed: 15360 != 15280
  110.     // // hint: results mismatch 1 unit tests failed. Terminate
  111.     // // подсказка: Неправильно распараллелен метод MatchDocument
  112.  
  113.     // auto last = std::unique(result_intersection.begin(), result_intersection.end());
  114.     // result_intersection.erase(last, result_intersection.end());
  115.     // result_intersection.erase(result_intersection.begin()); // стереть пустую строку из начала
  116.     // return {result_intersection, document_info_.at(document_id).status};
  117. }
  118.  
  119.  
  120.  
  121. //===========================================================================================================================
  122.  
  123. std::tuple<std::vector<std::string>, DocumentStatus> SearchServer::MatchDocument(const std::string& raw_query, int document_id) const {
  124.  
  125.     ThrowSpecialSymbolInText(raw_query);
  126.  
  127.     if (IsNegativeDocumentId(document_id)) {
  128.         throw std::invalid_argument("Negative document id"s);
  129.     }
  130.  
  131.     if (IsNonexistentDocumentId(document_id)) {
  132.         throw std::invalid_argument("Nonexistent document id"s);
  133.     }
  134.  
  135.     SearchServer::PlusMinusWords prepared_query = ParseQuery(raw_query);
  136.  
  137.     for (const std::string& minus_word : prepared_query.minus_words) {
  138.         if (TF_by_term_.count(minus_word) > 0) {
  139.             if (TF_by_term_.at(minus_word).count(document_id) > 0) {
  140.                 return {std::vector<std::string>{}, document_info_.at(document_id).status};
  141.             }
  142.         }
  143.     }
  144.  
  145.     std::set<std::string> plus_words_in_document;
  146.  
  147.     for (const std::string& plus_word : prepared_query.plus_words) {
  148.         if (TF_by_term_.count(plus_word) == 1) {
  149.             if (TF_by_term_.at(plus_word).count(document_id) == 1) {
  150.                 plus_words_in_document.insert(plus_word);
  151.             }
  152.         }
  153.     }
  154.  
  155.     std::vector<std::string> result_intersection; // интересно, если + слов как и - слов в документе не оказалось, пихать неинициализированный result_intersection это нормально?
  156.     for (const std::string& word : plus_words_in_document) {
  157.         result_intersection.push_back(word);
  158.     }
  159.  
  160.     return {result_intersection, document_info_.at(document_id).status};
  161. }
  162.  
  163. std::tuple<std::vector<std::string>, DocumentStatus> SearchServer::MatchDocument(std::execution::sequenced_policy, const std::string& raw_query, int document_id) const {
  164.     return MatchDocument(raw_query, document_id);
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement