Cod sursa(job #2818580)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 16 decembrie 2021 15:51:47
Problema Substr Scor 40
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.93 kb
#include <algorithm>
#include <iostream>
#include <fstream>
#include <map>
#include <vector>

#define LOGMAXN 14
#define MAXN (1 << LOGMAXN)

std::string s;
int sortingOrder[1 + LOGMAXN][MAXN + 1];

void getSortingOrder(const std::string& s, int pow) {
  if (pow == 0) {
    for (int i = 0; i < s.size(); ++i) {
      sortingOrder[0][i] = s[i] - 'a' + 1;
    }
    return;
  }

  std::vector<std::pair<std::pair<int, int>, int>> keyAndOriginalIndex;
  for (int i = 0; i < s.size() - (1 << pow) + 1; ++i) {
    keyAndOriginalIndex.emplace_back(std::make_pair(
            std::make_pair(sortingOrder[pow - 1][i],
                           sortingOrder[pow - 1][i + (1 << (pow - 1))]),
            i));
  }
  std::sort(keyAndOriginalIndex.begin(), keyAndOriginalIndex.end());
  int order = 1;
  std::pair<int, int> prev_key = keyAndOriginalIndex[0].first;
  sortingOrder[pow][keyAndOriginalIndex[0].second] = order;
  std::vector<std::pair<std::pair<int, int>, int>>::iterator it;
  for (it = keyAndOriginalIndex.begin(); it != keyAndOriginalIndex.end(); ++it) {
    if (it->first.first != prev_key.first ||
        it->first.second != prev_key.second) order++;
    sortingOrder[pow][it->second] = order;
    prev_key = it->first;
  }
}

struct HashingKey {
  std::vector<int> sortingOrders;
};

bool operator<(const HashingKey& left, const HashingKey& right) {
  for (int i = left.sortingOrders.size() - 1; i >= 0; --i) {
    if (left.sortingOrders[i] != right.sortingOrders[i]) {
      return left.sortingOrders[i] < right.sortingOrders[i];
    }
  }

  return false;
}

std::vector<int> getInvsortedLogBits(int length) {
  std::vector<int> sol;
  for (int i = 0; (1 << i) <= length; ++i) {
    if (length & (1 << i)) sol.push_back(i);
  }
  for (int i = 0; i < sol.size() / 2; ++i) {
    std::swap(sol[i], sol[sol.size() - i - 1]);
  }
  return sol;
}

HashingKey getKey(int pos, const std::vector<int>& logBits) {
  HashingKey key;
  for (const int invsortedLogBit : logBits) {
    key.sortingOrders.push_back(sortingOrder[invsortedLogBit][pos]);
    pos += (1 << invsortedLogBit);
  }
  return key;
}

int countMaxRepsForLength(int length) {
  std::vector<int> invsortedLogBits = getInvsortedLogBits(length);

  std::map<HashingKey, int> counts;
  int sol = 1;
  for (int i = 0; i < s.size() - length + 1; ++i)
    sol = std::max(sol, ++counts[getKey(i, invsortedLogBits)]);

  return sol;
}

int main() {
  std::ifstream in("substr.in");
  std::ofstream out("substr.out");

  long long n, k;
  in >> n >> k >> s;

  for (int pow = 0; (1 << pow) <= s.size(); ++pow) getSortingOrder(s, pow);

  // Binary search.
  int min = 1;
  int max = s.size();
  int sol = 1;
  while (min <= max) {
    int mid = (min + max) / 2;
    int maxReps = countMaxRepsForLength(mid);
    // std::cerr << "Max reps for len=" << mid << " is: " << maxReps << std::endl;
    if (maxReps >= k) {
      sol = mid;
      min = mid + 1;
    } else {
      max = mid - 1;
    }
  }

  out << sol << std::endl;

  return 0;
}