Cod sursa(job #2778681)

Utilizator radu.z5Zamfirescu Radu Ioan radu.z5 Data 1 octombrie 2021 23:46:30
Problema Trie Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
#include <fstream>
#include <list>

using namespace std;

#define ALPHABET_SIZE 26
#define map(c) c - 'a'

struct TrieNode {
	TrieNode *children[ALPHABET_SIZE];
	// de cate ori e folosit nodul curent pentru un cuvant
	size_t app;
	// marcheaza de cate ori nodul curent e sfarsit pentru un anumit cuvant
	size_t endCount;

	TrieNode() : app(0), endCount(0) {
		for (int i = 0; i < ALPHABET_SIZE; i++)
			children[i] = NULL;
	}
};

struct Trie {
	TrieNode *root;

	Trie() : root(new TrieNode()) {}

	void addWord(string &word) {
		TrieNode *it = root;
		string::iterator letter;

		it->app++;
		for (letter = word.begin(); letter != word.end(); letter++) {
			if (it->children[map(*letter)] == NULL)
				it->children[map(*letter)] = new TrieNode();
			it = it->children[map(*letter)];
			it->app++;
		}
		it->endCount++;
	}

	void erase(string &word) {
		TrieNode *it = root;
		string::iterator letter;

		list<TrieNode *> garbage;
		it->app--;

		for (letter = word.begin(); letter != word.end(); letter++) {
			TrieNode *parent = it;
			it = it->children[map(*letter)];
			it->app--;
			if (it->app == 0) {
				parent->children[map(*letter)] = NULL;
				garbage.push_back(it);
			}
		}
		it->endCount--;

		while (!garbage.empty()) {
			delete garbage.front();
			garbage.pop_front();
		}
	}

	size_t matchesOf(string &word) {
		TrieNode *it = root;
		string::iterator letter;

		for (letter = word.begin(); letter != word.end(); letter++) {
			if (it->children[map(*letter)] == NULL)
				return 0;
			it = it->children[map(*letter)];
		}
		return it->endCount;
	}

	size_t longestPrefixSizeOf(string &word) {
		TrieNode *it = root;
		string::iterator letter;
		size_t pathLength = 0;

		for (letter = word.begin(); letter != word.end(); letter++) {
			if (it->children[map(*letter)] == NULL)
				return pathLength;
			it = it->children[map(*letter)];
			++pathLength;
		}
		return pathLength;
	}

	~Trie() {
		TrieNode *it = root;
		list<TrieNode *> q;
		q.push_back(it);

		while (!q.empty()) {
			it = q.front();
			q.pop_front();

			for (size_t i = 0; i < 26; i++) {
				if (it->children[i])
					q.push_back(it->children[i]);
			}
			delete it;
		}
	}
};

void solve(ifstream &in, ofstream &out) {
	Trie *trie = new Trie();

	int code;
	string word;

	while (true) {
		// valoare care nu trebuie sa apara in input
		code = 4;
		in >> code;
		if (code != 4) {
			in >> word;
			if (code == 0)
				trie->addWord(word);
			else if (code == 1)
				trie->erase(word);
			else if (code == 2)
				out << trie->matchesOf(word) << '\n';
			else if (code == 3)
				out << trie->longestPrefixSizeOf(word) << '\n';
		} else {
			break;
		}
	}
	delete trie;
}

int main(void) {
	ifstream in("trie.in");
	ofstream out("trie.out");

	solve(in, out);

	in.close();
	out.close();
	return 0;
}