Cod sursa(job #3142713)

Utilizator daristyleBejan Darius-Ramon daristyle Data 23 iulie 2023 16:04:40
Problema Substr Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.16 kb
#include <fstream>

using namespace std;
ifstream fin("substr.in");
ofstream fout("substr.out");

const int N_MAX = (1 << 14);
const int HASHES = 3;
const int MODS[] = {666013, (int) 1e9 + 7, (int) 1e9 + 21};
const int BASE = 256;
const int OFFSET = '0';
const int NIL = -1;

template<typename Key, typename Value>
class Dictionary{
private:
		static const int MOD = 65353;
		struct Node{
				Key key;
				Value value;
		};
		Node node[N_MAX];
		int nxt[N_MAX];
		int head[MOD];
		int n;

		int hash(Key key){
			return key % MOD;
		}

		int find(Key x){
			int list = hash(x);
			int l = head[list];
			while(l != NIL && node[l].key != x)
				l = nxt[l];

			return l;
		}

public:
		Dictionary(){
			for(int i = 0; i < N_MAX; ++i)
				nxt[i] = NIL;
			for(int i = 0; i < MOD; ++i)
				head[i] = NIL;
			n = 0;
		}

		void add(Node x){
			int list = hash(x.key);
			node[n] = x;
			nxt[n] = head[list];
			head[list] = n;
			++n;
		}

		void remove(Key x){
			int list = hash(x);
			int l = head[list], prev = NIL;
			while(l != NIL && node[l].key != x){
				prev = l;
				l = nxt[l];
			}

			if(node[l].key == x){
				if(prev == NIL)
					head[list] = nxt[l];
				else
					nxt[prev] = nxt[l];
			}
		}

		const Value translate(Key x){
			int pos = find(x);
			Value ret{};
			if(pos != NIL)
				ret = node[pos].value;

			return ret;
		}

		Value& operator[](Key x){
			int pos = find(x);
			if(pos == NIL){
				Value aux{};
				add({x, aux});
				pos = n - 1;
			}

			return node[pos].value;
		}

		void clear(){
			for(int i = 0; i < n; ++i)
				nxt[i] = NIL;
			for(int i = 0; i < MOD; ++i)
				head[i] = NIL;
			n = 0;
		}
};

int lgpow(int b, int e, int mod){
	int p = 1;
	while(e){
		if(e & 1)
			p = (long long) p * b % mod;
		b = (long long) b * b % mod;
		e >>= 1;
	}

	return p;
}

struct Hash{
		int value, mod, base, base_power;

		void init(int _mod, int _base, int len){
			value = 0;
			mod = _mod;
			base = _base;
			base_power = lgpow(base, len - 1, mod);
		}

		void add(char ch){
			value = ((unsigned long long) value * base % mod + ch - OFFSET);
			if(value >= mod)
				value -= mod;

		}

		void remove(char ch){
			value = value - ((unsigned long long) (ch - OFFSET) * base_power % mod);
			if(value < 0)
				value += mod;
		}

		int compute(char* s, int slen){
			int val = 0;
			for(int i = 0; i < slen; ++i){
				val = ((unsigned long long) val * base % mod + s[i] - OFFSET);
				if(val >= mod)
					val -= mod;
			}

			return val;
		}
};

char s[N_MAX + 1];
Dictionary<int, short> f;

bool Check(int len, int k, char s[], int slen){
	Hash h;
	int it = 0;
	bool ret = true;
	while(it < HASHES && ret){
		h.init(MODS[it], BASE, len);
		h.value = h.compute(s, len - 1);

		int max = 0;

		for(int i = len - 1; i < slen; ++i){
			h.add(s[i]);
			++f[h.value];
			if(f[h.value] > max)
				max = f[h.value];
			h.remove(s[i - len + 1]);
		}

		if(max < k)
			ret = false;

		f.clear();

		++it;
	}

	return ret;
}

int main(){
	int slen, k;
	fin >> slen >> k;
	fin.get();
	fin.getline(s, slen + 1);

	int b = 0, e = slen - k + 1 + 1, mid;

	while(e - b > 1){
		mid = (b + e) / 2;
		if(Check(mid, k, s, slen))
			b = mid;
		else
			e = mid;
	}

	fout << b << '\n';

	fin.close();
	fout.close();
	return 0;
}