Pagini recente » Cod sursa (job #1642873) | Cod sursa (job #655300) | Cod sursa (job #3221980) | Cod sursa (job #237602) | Cod sursa (job #2818716)
#include <algorithm>
#include <iostream>
#include <fstream>
#include <map>
#include <unordered_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];
}
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;
};
namespace std {
template<>
struct hash<HashingKey> {
std::size_t operator()(const HashingKey& k) const {
size_t sol = 0;
for (int i = 0; i < k.sortingOrders.size(); ++i) {
sol = (sol ^ hash<int>()(k.sortingOrders[i]));
}
return sol;
}
};
} // namespace std
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 false;
}
}
return true;
}
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::unordered_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;
}