Pagini recente » Cod sursa (job #3138142) | Cod sursa (job #2352537) | Cod sursa (job #3214433) | Cod sursa (job #2369508) | Cod sursa (job #2281595)
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
struct trie
{
/// Numarul de cuvinte prezente
int number;
/// Numarul de cuvinte care contin acest cuvant (fara number)
int children;
/// Vector din cupluri < caracter, pointer > pentru muchii
vector < pair < char, trie* > > next;
/// Constructor (initializeaza variabilele cu 0 la creare)
trie()
{
number = children = 0;
}
} *start;
void trie_insert(trie*, char*);
bool trie_delete(trie*, char*);
int trie_count(trie*, char*);
int trie_prefix(trie*, char*);
int main()
{
freopen("trie.in", "r", stdin);
freopen("trie.out", "w", stdout);
/// Radacina arborelui (reprezinta cuvantul null "")
start = new trie;
char str[32];
while(fgets(str, 32, stdin))
{
switch(str[0])
{
case '0': trie_insert(start, str+2); break;
case '1': trie_delete(start, str+2); break;
case '2': printf("%i\n", trie_count(start, str+2)); break;
case '3': printf("%i\n", trie_prefix(start, str+2)); break;
default: return 0;
}
}
return 0;
}
/// Calculeaza lungimea celui mai lung prefix cu orice alt cuvant din lista
/// (cuvantul complet poate exista deja in lista)
int trie_prefix(trie *nod, char *str)
{
int pos = 0;
while(*str != '\n')
{
/// Cautam muchia cu caracterul (*str)
vector < pair < char, trie* > > :: iterator it;
for(it = nod->next.begin(); it != nod->next.end(); ++it)
if(it->first == *str)
break;
/// Daca am ajuns la pozitia dupa elementele vectorului ( .end() )
/// inseamna ca nu am gasit muchia (iteratorul a continuat pana la sfarsit)
if(it == nod->next.end())
break;
/// Sarim (prin muchia it) la urmatorul nod
nod = it->second;
str++;
pos++;
}
return pos;
}
/// Returneaza numarul de aparitii a cuvantului str
int trie_count(trie *nod, char *str)
{
while(*str != '\n')
{
/// Cautam muchia cu caracterul (*str)
vector < pair < char, trie* > > :: iterator it;
for(it = nod->next.begin(); it != nod->next.end(); ++it)
if(it->first == *str)
break;
/// Daca am ajuns la pozitia dupa elementele vectorului ( .end() )
/// inseamna ca nu am gasit muchia (iteratorul a continuat pana la sfarsit)
/// si suntem in cazul in care nu exista cuvantul in arbore (numarul de aparitii este 0)
if(it == nod->next.end())
return 0;
/// Sarim (prin muchia it) la urmatorul nod
nod = it->second;
str++;
}
return nod->number;
}
/**
Scadem numarul de aparitii a cuvantului str
si stergem nodul daca numarul de aparitii devine 0
(stergem si parintii ramasi frunze pana cand unul din ei nu este parte
dintr-un cuvant prezent (nu are fii si nici nu reprezinta sfarsitul unui cuvant)
**/
bool trie_delete(trie *nod, char *str)
{
/// Daca am ajuns la capatul cuvantului, scadem numarul de aparitii cu 1
if(*str == '\n')
nod->number--;
else
{
/// Cautam muchia cu caracterul (*str)
/// Problema asigura ca cuvantul sters este prezent
vector < pair < char, trie* > > :: iterator it;
for(it = nod->next.begin(); it != nod->next.end(); ++it)
if(it->first == *str)
break;
/// Continuam stergerea
if(trie_delete(it->second, str+1))
{
/// Daca nodul urmator a fost sters,
/// actualizam nodul curent
nod->children--;
nod->next.erase(it);
}
}
/**
Daca nodul nu face parte din alte cuvinte prezente,
nu reprezinta sfarsitul unui cuvant si nu coincide cu radacina
stergem nodul (eliberam memoria) si returnam true pentru a semnala
nodului parinte la intoarcerea pe stiva ca nodul acesta a fost sters
**/
if(nod->children == 0 && nod->number == 0 && nod != start)
{
delete nod;
return true;
}
return false;
}
/// Crestem numarul de aparitii a cuvantului str
/// si creeam lantul de muchii in caz ca nu a fost creat inca
void trie_insert(trie *nod, char *str)
{
while(*str != '\n')
{
/// Cautam muchia cu caracterul (*str)
vector < pair < char, trie* > > :: iterator it;
for(it = nod->next.begin(); it != nod->next.end(); ++it)
if(it->first == *str)
break;
/**
Daca am ajuns la pozitia dupa elementele vectorului ( .end() )
inseamna ca nu am gasit muchia (iteratorul a continuat pana la sfarsit),
astfel, alocam spatiu pentru nodul copil si ii tinem minte adresa
in vectorul de muchii al nodului curent
**/
if(it == nod->next.end())
{
nod->next.push_back(make_pair(*str, new trie));
/// Pentru ca nu am ajuns inca la sfarsit,
/// inseamna ca nodul curent face parte dintr-un cuvant
nod->children++;
nod = nod->next.back().second;
}
else
nod = it->second;
str++;
}
/// La sfarist nodul va reprezenta cuvantul complet str (crestem numarul de aparitii)
nod->number++;
}