Advertisement
coloriot

HA18_lowerbound

Aug 6th, 2024 (edited)
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.90 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. // Решение с более понятным циклом while с lower bound
  4.  
  5. using namespace std;
  6.  
  7. class String {
  8. private:
  9.     char* data;
  10.     int length;
  11.  
  12. public:
  13.     String() : data(nullptr), length(0) {}
  14.  
  15.     String(const char* str, int len) : length(len) {
  16.         data = new char[length];
  17.         for (int i = 0; i < length; i++) {
  18.             data[i] = str[i];
  19.         }
  20.     }
  21.  
  22.     String(const String& other) : length(other.length) {
  23.         data = new char[length];
  24.         for (int i = 0; i < length; i++) {
  25.             data[i] = other.data[i];
  26.         }
  27.     }
  28.  
  29.     ~String() {
  30.         delete[] data;
  31.     }
  32.  
  33.     String& operator=(const String& other) {
  34.         if (this == &other)
  35.             return *this;
  36.  
  37.         delete[] data;
  38.         length = other.length;
  39.         data = new char[length];
  40.         for (int i = 0; i < length; i++) {
  41.             data[i] = other.data[i];
  42.         }
  43.         return *this;
  44.     }
  45.  
  46.     bool startsWith(const String& prefix) const {
  47.         if (prefix.length > length)
  48.             return false;
  49.  
  50.         for (int i = 0; i < prefix.length; i++) {
  51.             if (data[i] != prefix.data[i])
  52.                 return false;
  53.         }
  54.         return true;
  55.     }
  56.  
  57.     bool operator<(const String& other) const {
  58.         int minLength = length < other.length ? length : other.length;
  59.         for (int i = 0; i < minLength; i++) {
  60.             if (data[i] < other.data[i])
  61.                 return true;
  62.  
  63.             if (data[i] > other.data[i])
  64.                 return false;
  65.         }
  66.         return length < other.length;
  67.     }
  68.  
  69.     bool operator==(const String& other) const {
  70.         if (length != other.length)
  71.             return false;
  72.  
  73.         for (int i = 0; i < length; i++) {
  74.             if (data[i] != other.data[i])
  75.                 return false;
  76.         }
  77.         return true;
  78.     }
  79.  
  80.     int size() const {
  81.         return length;
  82.     }
  83.  
  84.     char operator[](int index) const {
  85.         return data[index];
  86.     }
  87.  
  88.     friend istream& operator>>(istream& is, String& str) {
  89.         string buffer;
  90.         is >> buffer;
  91.         str = String(buffer.data(), buffer.size());
  92.         return is;
  93.     }
  94.  
  95.     friend ostream& operator<<(ostream& os, const String& str) {
  96.         for (int i = 0; i < str.length; i++) {
  97.             os << str.data[i];
  98.         }
  99.         return os;
  100.     }
  101. };
  102.  
  103. int findMidpoint(int left, int right) {
  104.     return (left + right) / 2;
  105. }
  106.  
  107. int main() {
  108.     int N, Q;
  109.     cin >> N >> Q;
  110.  
  111.     String* dictionary = new String[N];
  112.     for (int i = 0; i < N; ++i) {
  113.         cin >> dictionary[i];
  114.     }
  115.  
  116.     int* results = new int[Q];
  117.  
  118.     for (int i = 0; i < Q; ++i) {
  119.         String prefix;
  120.         int k;
  121.         cin >> k >> prefix;
  122.  
  123.         int count = 0;
  124.         results[i] = -1;
  125.  
  126.         int left = 0, right = N;
  127.  
  128.         // Поиск за O(lgn) с использованием lower bound
  129.         while (left < right) {
  130.             int mid = findMidpoint(left, right);
  131.             if (dictionary[mid] < prefix) {
  132.                 // Если mid меньше префикса, сдвигаем lower bound
  133.                 left = mid + 1;
  134.             } else {
  135.                 // Иначе сдвигаем upper bound
  136.                 right = mid;
  137.             }
  138.         }
  139.  
  140.         // Подсчет строк, начинающихся с префикса
  141.         for (int j = left; j < N; ++j) {
  142.             if (dictionary[j].startsWith(prefix)) {
  143.                 count++;
  144.                 if (count == k) { // Если найдена k-я строка
  145.                     results[i] = j + 1;
  146.                     break;
  147.                 }
  148.             } else {
  149.                 break;
  150.             }
  151.         }
  152.     }
  153.  
  154.     for (int i = 0; i < Q; ++i) {
  155.         cout << results[i] << '\n';
  156.     }
  157.  
  158.     delete[] dictionary;
  159.     delete[] results;
  160.  
  161.     return 0;
  162. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement