Cod sursa(job #710838)

Utilizator yamahaFMI Maria Stoica yamaha Data 10 martie 2012 20:54:46
Problema Trie Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.28 kb
#include<cstdio>
#include<cstring>

using namespace std;

// ch va retine un numar int
// el va indica pozitia in alfabet a literei date
// a - a = 0 // prima litera
// b - a = 1 // a doua litera
// l - a = 11 // a 11-a litera etc.
#define ch (*s - 'a')

// Trie-ul:
struct Trie
{
  int cuvinte; // numarul de cuvinte de la nodul respectiv in josul triei
  int nrfii; // numarul de ramificatii din nodul respectiv == litere distincte
  Trie *edge[26]; // sunt 26 litere "a...z" fara diacritice
  
  Trie() // initializarea Trie-ului se va face la fiecare new Trie
  {
    cuvinte = 0;
    nrfii = 0;
    memset(edge, 0, sizeof(edge));
  }
};
Trie *T = new Trie;

// Cele 4 functii:
void inserare(Trie *nod, char *s); // inserare
int stergere(Trie *nod, char *s); // stergere
int nr_cuvinte(Trie *nod, char *s); // numara cuvintele
int l_prefix(Trie *nod, char *s, int k); // numara lungimea prefixul

int main ()
{
  freopen("trie.in","r",stdin);
  freopen("trie.out","w",stdout);
  
  int r;
  char line[32];
  fgets(line, 32, stdin);
  
  while(!feof(stdin))
  {
    switch(line[0])
    {
      // line+2 == de aici incepe cuvantul
      case '0': inserare(T, line+2); break;
      case '1': stergere(T, line+2); break;
      case '2': r = nr_cuvinte(T, line+2), printf("%d\n", r); break;
      case '3': r = l_prefix(T, line+2, 0), printf("%d\n", r); break;
    }
    fgets(line, 32, stdin);
  }

  return 0;
}

void inserare(Trie *nod, char *s)
{
  if(*s == '\n') { nod->cuvinte++; return; } // daca se termina de parcurs *s
  if(nod->edge[ch]==0)                       
  {                                          // daca *s este un cuvant care se repeta atunci
    nod->edge[ch] = new Trie;                // va creste nr de cuvinte din nodul ultimei litere
    nod->nrfii++;
  }
  inserare(nod->edge[ch], s+1); // astfel se trece prin fiecare litera a cuvantului
}

int stergere(Trie *nod, char *s)
{
  if(*s == '\n') nod->cuvinte--; // asta e pentru cazurile in care cuvantul dat spre stergere
                                 // este inclus in intregime in prefixul comun al altora
                                 // exemplu: *s==tra si in trie se afla "trabant"
                                 // ramura "trabant", in loc sa contina 2 cuvinte va contine doar 1
                                 
  else if(stergere(nod->edge[ch], s+1)) // se parcurge astfel cuvantul, litera cu litera
  {
    nod->edge[ch] = 0;
    nod->nrfii--;
  }
  if(nod != T && nod->cuvinte == 0 && nod->nrfii == 0)  // si cand se ajunge la ultima litera o sterge
  {                                                     // apoi penultima litera a devenit ultima litera
    delete nod;                                         // si o sterge pana la radacina comuna cu alt cuvant
    return 1;                                           // daca exista sau pana la radacina triei
  }
  return 0;
}

int nr_cuvinte(Trie *nod, char *s)
{
  if(*s == '\n') return nod->cuvinte; // nr de aparitii ale unui cuvant se afla in nodul ultimei sale litere
  if(nod->edge[ch])
    return nr_cuvinte(nod->edge[ch], s+1);
  return 0;
}

int l_prefix(Trie *nod, char *s, int k)
{
  if(*s == '\n' || nod->edge[ch] == 0) return k;
  return l_prefix(nod->edge[ch], s+1, k+1);
}