Cod sursa(job #1512404)

Utilizator stoianmihailStoian Mihail stoianmihail Data 28 octombrie 2015 00:04:10
Problema Trie Scor 100
Compilator c Status done
Runda Arhiva educationala Marime 3.2 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define Nadejde 100000
#define Smerenie 21
#define NIL -1

int N, size;
int task[Nadejde];            // task[i] este tipul intrebarii "i".
int count[Nadejde];           // count[i] este frecventa pozitiei "i".
char s[Nadejde][Smerenie];    // sirurile din intrebari.
char dict[Nadejde][Smerenie]; // dictionarul sortat.

/** max(X, Y). **/
int MAX(int X, int Y) {
  return X > Y ? X : Y;
}

/** Sorteaza crescator dictionarul. **/
void sort(int begin, int end) {
  int b = begin, e = end;
  char tmp[Smerenie], pivot[Smerenie];
  strcpy(pivot, dict[(b + e) >> 1]);

  while (b <= e) {
    while (strcmp(dict[b], pivot) < 0) {
      b++;
    }
    while (strcmp(dict[e], pivot) > 0) {
      e--;
    }
    if (b <= e) {
      strcpy(tmp, dict[b]);
      strcpy(dict[b++], dict[e]);
      strcpy(dict[e--], tmp);
    }
  }
  if (begin < e) {
    sort(begin, e);
  }
  if (b < end) {
    sort(b, end);
  }
}

/** Sterge dublurile. **/
void unique() {
  int i, count = 1;
  for (i = 1; i < size; i++) {
    if (strcmp(dict[i], dict[count - 1])) {
      strcpy(dict[count++], dict[i]);
    }
  }
  size = count;
}

/** Cauta binar sirul "s" in dictionar. **/
int bSearch(int lo, int hi, char *s) {
  while (hi - lo > 1) {
    int mid = (lo + hi) >> 1;
    if (strcmp(dict[mid], s) > 0) {
      hi = mid;
    } else {
      lo = mid;
    }
  }
  return lo;
}

/** Adauga la "count" valoarea "val". **/
void add(char *s, int val) {
  count[bSearch(NIL, size, s)] += val;
}

/** Gaseste frecventa sirului "s". **/
int get(char *s) {
  int pos = bSearch(NIL, size, s);
  return (pos < 0) || (strcmp(dict[pos], s)) ? 0 : count[pos];
}

/** Lungimea celui mai lung prefix comun. **/
int common(char *u, char *v) {
  int pos = 0;
  while ((u[pos]) && (u[pos] == v[pos])) {
    pos++;
  }
  return pos;
}

/** Raspunde la intrebarile de tip 3. **/
int match(char *s) {
  int pos = bSearch(NIL, size, s);
  /* Daca sirul "s" este mai mic decat celalte siruri. */
  if (pos < 0) {
    do {
      pos++;
    } while (!count[pos]);
    return common(s, dict[pos]);
  } else {
    /* Afla cuvintele cu care "s" face prefixul comun maxim. */
    int lo = pos, hi = pos + 1;
    while ((lo >= 0) && (!count[lo])) {
      lo--;
    }
    while ((hi < size) && (!count[hi])) {
      hi++;
    }
    return MAX(lo >= 0 ? common(s, dict[lo]) : 0, hi < size ? common(s, dict[hi]) : 0);
  }
}

int main(void) {
  int i;
  FILE *f = fopen("trie.in", "r");

  /* Citeste intrebarile si memoreaza-le. */
  while (fscanf(f, "%d %s", &task[N], s[N]) == 2) {
    if (!task[N]) {
      strcpy(dict[size++], s[N]);
    }
    N++;
  }
  fclose(f);

  f = fopen("trie.out", "w");

  sort(0, size - 1);
  unique();

  /* Raspunde la intrebari. */
  for (i = 0; i < N; i++) {
    switch(task[i]) {
      case 0 : add(s[i], -NIL);
        break;
      case 1 : add(s[i], NIL);
        break;
      case 2 : fprintf(f, "%d\n", get(s[i]));
        break;
      case 3 : fprintf(f, "%d\n", match(s[i]));
        break;
    }
  }
  fclose(f);

  /// Multumim Doamne!
  puts("Doamne ajuta!");
  return 0;
}