Pagini recente » Cod sursa (job #3223585) | Cod sursa (job #1538716) | Cod sursa (job #473942) | Cod sursa (job #2452299) | Cod sursa (job #2446099)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <string>
#define FISIN "substr.in"
#define FISOUT "substr.out"
class Solution {
private:
public:
Solution() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
}
int longestDupSubstring(std::string s, unsigned k) {
if (s.empty()) return 0;
const unsigned n = s.size();
unsigned log_size = 0;
for (unsigned size = 1; size <= n; size <<= 1) ++log_size;
std::vector<std::vector<int> > pattern_id(log_size);
pattern_id.reserve(log_size);
std::vector<int>& patterns = pattern_id[0];
patterns.reserve(n);
for (const char ch : s) patterns.push_back(int{ch});
for (unsigned i = 1, step = 1; i < pattern_id.size(); ++i, step <<= 1) {
// printf("%u %u\n", i, step);
std::vector<int>& old_patterns = pattern_id[i - 1];
std::vector<int>& new_patterns = pattern_id[i];
// Normalize old position.
{
std::unordered_map<int, unsigned> position;
for (int& pattern : old_patterns) {
if (pattern == -1) continue;
auto it = position.find(pattern);
if (it != position.end()) {
pattern = it->second;
} else {
unsigned new_pattern = position.size();
position.insert(it, {pattern, new_pattern});
pattern = new_pattern;
}
}
}
for (unsigned index = 0; index < n; ++index) {
if (index + step >= n || old_patterns[index + step] == -1) {
new_patterns.push_back(-1);
continue;
}
new_patterns.push_back(old_patterns[index] * n + old_patterns[index + step]);
}
}
// for (unsigned i = 0; i < pattern_id.size(); ++i) {
// for (unsigned j = 0; j < pattern_id[i].size(); ++j) {
// printf("%d ", pattern_id[i][j]);
// }
// printf("\n");
// }
std::vector<std::vector<unsigned> > old_groups(1);
for (unsigned i = 0; i < n; ++i) old_groups.back().push_back(i);
unsigned len = 0;
for (int log_step = log_size; log_step >=0; --log_step) {
std::vector<std::vector<unsigned> > new_groups;
for (std::vector<unsigned>& old_group : old_groups) {
std::unordered_map<int, std::vector<unsigned> > group_map;
for (const unsigned start_location : old_group) {
if (start_location + len + (1 << log_step) > n) continue;
group_map[pattern_id[log_step][start_location + len]].push_back(start_location);
}
for (std::pair<const int, std::vector<unsigned> >& entry : group_map) {
if (entry.second.size() < k) continue;
new_groups.push_back(std::move(entry.second));
}
}
if (new_groups.size() > 0) {
len += (1 << log_step);
old_groups.swap(new_groups);
}
}
return len;
}
};
int main() {
FILE *fin = fopen(FISIN, "rt");
FILE *fout = fopen(FISOUT, "wt");
int n, k;
char s[16385];
fscanf(fin, "%d %d\n%s", &n, &k, s);
fprintf(fout, "%d\n", Solution().longestDupSubstring(s, k));
fclose(fout);
fclose(fin);
return 0;
}