Cod sursa(job #2446099)

Utilizator daniel.dumitranDaniel Dumitran daniel.dumitran Data 7 august 2019 09:00:33
Problema Substr Scor 60
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.19 kb
#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;
}