Pagini recente » Cod sursa (job #3248476) | Cod sursa (job #1145786) | Cod sursa (job #1516005) | Cod sursa (job #822149) | Cod sursa (job #1558582)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define P 29850523
#define E 29850517
#define MOD 99991
#define Nadejde 16390
#define UTF8 256
#define BASE 67
#define SIGMA 26
typedef struct {
int p, e, end, count, next;
} list;
int N, K, len;
int max, flag;
char s[Nadejde]; // sirul nostru.
int code[UTF8]; // codul hash al fiecarui caracter.
int buff, adj[MOD]; // capetele listelor din tabela.
list l[Nadejde + 1]; // tabela hash.
int pBases[Nadejde + 1], eBases[Nadejde + 1];
/** max(X, Y). **/
int MAX(int X, int Y) {
return X > Y ? X : Y;
}
/** Precalculeaza bazele si sirul "code". **/
void getBases() {
int i;
pBases[0] = eBases[0] = 1;
for (i = 1; i <= N; i++) {
pBases[i] = (pBases[i - 1] * BASE) % P;
eBases[i] = (eBases[i - 1] * BASE) % E;
}
char c;
for (c = 'a'; c <= 'z'; c++) {
code[c] = c - 'a' + 1;
}
for (c = 'A'; c <= 'Z'; c++) {
code[c] = c - 'A' + SIGMA + 1;
}
for (c = '0'; c <= '9'; c++) {
code[c] = c - '0' + (SIGMA << 1) + 2;
}
}
/** Initializeaza tabela hash. **/
void init() {
int i;
for (i = buff = 0; i < MOD; i++) {
adj[i] = 0;
}
}
/** Adauga in tabela hash perechea (p, e, i). **/
void add(int h, int p, int e, int i) {
l[++buff].p = p;
l[buff].e = e;
l[buff].end = i;
l[buff].count = 1;
l[buff].next = adj[h];
adj[h] = buff;
}
int equal(int i, int j) {
int k;
for (k = 0; (k < len) && (s[i - k] == s[j - k]); k++);
return k == len;
}
/** Cauta perechea (p, e, i) in tabela. **/
void find(int p, int e, int i) {
int pos, same = 0, h = p % MOD;
for (pos = adj[h]; (pos != 0) && (!same); pos = l[pos].next) {
if ((l[pos].p == p) && (l[pos].e == e)) {
same = 1;
max = MAX(max, ++l[pos].count);
if (max == K) {
flag = 1;
}
}
}
/* Daca nu am gasit-o, o punem in tabela. */
if (!same) {
add(h, p, e, i);
}
}
/** Vezi daca sunt mai mult de K aparitii de lungime "len". **/
int try() {
int i, lim = len - 1, pHash = 0, eHash = 0;
init();
max = 1;
for (i = flag = 0; i < lim; i++) {
pHash = (pHash * BASE + code[s[i]]) % P;
eHash = (eHash * BASE + code[s[i]]) % E;
}
for (i = lim; (i < N) && (!flag); i++) {
pHash = (pHash * BASE + code[s[i]]) % P;
eHash = (eHash * BASE + code[s[i]]) % E;
find(pHash, eHash, i);
pHash = ((pHash - pBases[lim] * code[s[i - lim]]) % P + P) % P;
eHash = ((eHash - eBases[lim] * code[s[i - lim]]) % E + E) % E;
}
return (max >= K);
}
/** Cauta binar rezultatul. **/
int bSearch(int lo, int hi) {
while (hi - lo > 1) {
len = (lo + hi) >> 1;
printf("%d\n", len);
if (try()) {
lo = len;
} else {
hi = len;
}
}
return lo;
}
int main(void) {
FILE *f = fopen("substr.in", "r");
/* Citirea datelor. */
fscanf(f, "%d %d\n%s", &N, &K, s);
fclose(f);
/* Precalcularea bazelor. */
getBases();
/* Calcularea solutiei si afisarea ei. */
//freopen("substr.out", "w", stdout);
fprintf(stdout, "%d\n", bSearch(0, N + 1));
fclose(stdout);
/// Multumim Doamne!
puts("Doamne ajuta!");
return 0;
}