Pagini recente » Cod sursa (job #2483023) | Cod sursa (job #2111474) | Cod sursa (job #2284721) | Cod sursa (job #2205385) | Cod sursa (job #1160722)
#include <cstring>
#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
const int MAX_NODES = 1000000;
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() {}
Trie(int father) {
parent = father;
}
} trie[MAX_NODES];
vector<int> stack;
int k = 0;
void insert() {
int node = 1; //nodul curent, initial in radacina (1)
for(int pos = 0; pos < static_cast<int>(word.size()); ++ pos) {
++ trie[node].weight;
if(!trie[node].sons[word[pos] - 'a']) {
//trebuie sa adaugam un nod in trie
if(stack.empty()) { //nu exista nici o casuta goala
trie[++ k] = Trie(node);
trie[node].sons[word[pos] - 'a'] = k;
} 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 != 1 /* sa nu cumva sa stergem radacina */ && trie[node].weight == 0) {
trie[trie[node].parent].sons[*(it - 1) - 'a'] = 0; //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 != 1 && trie[node].weight == 0) {
trie[trie[node].parent].sons[*(it - 1) - 'a'] = 0;
stack.push_back(node);
}
}
int get_to() {
int node = 1, pos = 0;
while(pos < static_cast<int>(word.size()) && node) {
node = trie[node].sons[word[pos] - 'a'];
++ pos;
}
return node;
}
int query() {
int node = 1, pos = 0;
while(pos < static_cast<int>(word.size()) && node) {
node = trie[node].sons[word[pos] - 'a'];
++ pos;
}
if(pos == static_cast<int>(word.size()) && node) {
return pos;
}
return pos - 1;
}
int main() {
ifstream fin("trie.in");
ofstream fout("trie.out");
int op;
trie[++ k] = 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(1, 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;
}