Pagini recente » Cod sursa (job #148757) | Cod sursa (job #2395427) | Cod sursa (job #1728082) | Cod sursa (job #1552282) | Cod sursa (job #1160700)
#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
string word;
struct Trie {
int sons[26]; //indicii fiilor prin fiecare litera
int parent; //indicele tatalui
int count; //numarul de aparitii ale cuvantului curent in dictionar
int weight; //numarul de cuvinte din subarbore
Trie() {
for(int i = 0; i < 26; ++ i) {
sons[i] = -1;
}
parent = -1;
weight = count = 0;
}
Trie(int father) {
for(int i = 0; i < 26; ++ i) {
sons[i] = -1;
}
parent = father;
weight = count = 0;
}
};
vector<Trie> trie;
vector<int> stack;
void insert() {
int node = 0; //nodul curent, initial in radacina (0)
for(int pos = 0; pos < static_cast<int>(word.size()); ++ pos) {
++ trie[node].weight;
if(trie[node].sons[word[pos] - 'a'] == -1) {
//trebuie sa adaugam un nod in trie
if(stack.empty()) { //nu exista nici o casuta goala
trie.push_back(Trie(node));
trie[node].sons[word[pos] - 'a'] = static_cast<int>(trie.size()) - 1;
} else { //exista un loc gol, nu merita sa alocam altceva
trie[stack.back()] = Trie(node);
trie[node].sons[word[pos] - 'a'] = stack.back();
stack.pop_back();
}
}
node = trie[node].sons[word[pos] - 'a'];
}
++ trie[node].weight;
++ trie[node].count;
}
void erase(int node, const string :: iterator &it, const string :: iterator &end) {
if(it == end) {
-- trie[node].count;
-- trie[node].weight;
if(node /* sa nu cumva sa stergem radacina */ && trie[node].weight == 0) {
trie[trie[node].parent].sons[*(it - 1) - 'a'] = -1; //nu mai este fiul nimanui, nu mai exista!
stack.push_back(node); //casuta nodului curent devine goala, o adaugam in stiva
}
return;
}
erase(trie[node].sons[*it - 'a'], it + 1, end); //trebuie facut recursiv, ca la iesirea din recursivitate sa vedem
//daca stergem fizic si nodul curent
-- trie[node].weight;
if(node && trie[node].weight == 0) {
trie[trie[node].parent].sons[*(it - 1) - 'a'] = -1;
stack.push_back(node);
}
}
int get_to() {
int node = 0, pos = 0;
while(pos < static_cast<int>(word.size()) && node != -1) {
node = trie[node].sons[word[pos] - 'a'];
++ pos;
}
return node;
}
int query() {
int node = 0, pos = 0;
while(pos < static_cast<int>(word.size()) && node != -1) {
node = trie[node].sons[word[pos] - 'a'];
++ pos;
}
return pos - 1;
}
int main() {
ifstream fin("trie.in");
ofstream fout("trie.out");
int op;
trie.push_back(Trie());
//stiva memoreaza pozitiile din Trie care sunt goale, deci in care pot aloca noduri
//mereu o sa fie in stiva trie.size(), deoarece mereu este o varianta sa dau pur si simplu push_back
while(fin >> op >> word) {
if(op == 0) {
insert();
} else if(op == 1) {
erase(0, word.begin(), word.end());
} else if(op == 2) {
int node = get_to();
if(node != -1) {
fout << trie[node].count << "\n";
} else {
fout << "0\n";
}
} else {
fout << query() << "\n";
}
}
return 0;
}