Cod sursa(job #1560539)

Utilizator PatrunjeluMarginean Bogdan Alexandru Patrunjelu Data 2 ianuarie 2016 20:16:05
Problema Trie Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.74 kb
#include <fstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <cstdio>

using InstructionWordPair = std::tuple<char, std::string>;

struct TrieNode
{
	TrieNode()
	{
		for (int i = 0; i < 26; ++i)
		{
			Children[i] = nullptr;
		}
	}

	int OccurrenceCount = 0;
	int ChildCount = 0;
	TrieNode* Children[26];
};

TrieNode* root = new TrieNode();

InstructionWordPair LineToInstructionAndWord(const std::string& line)
{
	char instruction = line[0];
	std::string word = line.substr(2);
	return std::make_tuple(instruction, word);
}

namespace detail
{
	int CharToChildIndex(char c)
	{
		return c - 'a';
	}

	bool Delete(TrieNode* node, const std::string& word, int indexInWord)
	{
		if (indexInWord == word.length())
		{
			node->OccurrenceCount--;
		}
		else
		{
			int childIndex = CharToChildIndex(word[indexInWord]);
			if (Delete(node->Children[childIndex], word, indexInWord + 1))
			{
				delete node->Children[childIndex];
				node->Children[childIndex] = nullptr;
				node->ChildCount--;
			}
		}
		return node->OccurrenceCount <= 0 && node->ChildCount <= 0;
	}

	int CountLongestCommonPrefix(const TrieNode* node, const std::string& word, int indexInWord, int lengthSoFar)
	{
		if (indexInWord == word.length())
		{
			return lengthSoFar;
		}
		int childIndex = CharToChildIndex(word[indexInWord]);
		if (node->Children[childIndex] != nullptr)
		{
			return CountLongestCommonPrefix(node->Children[childIndex], word, indexInWord + 1, lengthSoFar + 1);
		}
		return lengthSoFar;
	}

	void AddWordOccurrence(TrieNode* node, const std::string& word, int indexInWord)
	{
		if (indexInWord == word.length())
		{
			node->OccurrenceCount++;
		}
		else
		{
			int childIndex = CharToChildIndex(word[indexInWord]);
			if (node->Children[childIndex] == nullptr)
			{
				auto newNode = new TrieNode();
				node->Children[childIndex] = newNode;
				node->ChildCount++;
				AddWordOccurrence(newNode, word, indexInWord + 1);
			}
			else
			{
				AddWordOccurrence(node->Children[childIndex], word, indexInWord + 1);
			}
		}
	}

	int CountOccurrences(TrieNode* node, const std::string& word, int indexInWord)
	{
		if (indexInWord == word.length())
		{
			return node->OccurrenceCount;
		}
		int childIndex = CharToChildIndex(word[indexInWord]);
		if (node->Children[childIndex] != nullptr)
		{
			return CountOccurrences(node->Children[childIndex], word, indexInWord + 1);
		}
		return 0;
	}
}

void AddWordOccurrence(const std::string& word)
{
	detail::AddWordOccurrence(root, word, 0);
}

void DeleteWordOccurrence(const std::string& word)
{
	detail::Delete(root, word, 0);
}

int CountOccurrences(const std::string& word)
{
	return detail::CountOccurrences(root, word, 0);
}

int CountLongestCommonPrefix(const std::string& word)
{
	return detail::CountLongestCommonPrefix(root, word, 0, 0);
}

void Execute(const InstructionWordPair& instructionAndWord)
{
	const char instruction = std::get<0>(instructionAndWord);
	const std::string word = std::get<1>(instructionAndWord);
	switch (instruction)
	{
	case('0') :
		AddWordOccurrence(word);
		break;
	case('1') :
		DeleteWordOccurrence(word);
		break;
	case('2') :
		printf("%d\n", CountOccurrences(word));
		break;
	case('3') :
		printf("%d\n", CountLongestCommonPrefix(word));
		break;
	default:
		break;
	}
}

int main()
{
	char line[32];
	freopen("trie.in", "r", stdin);
	freopen("trie.out", "w", stdout);
	fgets(line, 32, stdin);
	while (!feof(stdin))
	{
		char instruction = line[0];
		int lineLen = 0;
		do
		{
			lineLen++;
		} while (line[lineLen] != '\n');
		std::string word(line + 2, line + lineLen);
		Execute(std::make_tuple(instruction, word));
		fgets(line, 32, stdin);
	}
}