Cod sursa(job #1560532)

Utilizator PatrunjeluMarginean Bogdan Alexandru Patrunjelu Data 2 ianuarie 2016 20:08:20
Problema Trie Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.35 kb
#include <fstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <memory>

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

struct TrieNode
{
	int OccurrenceCount = 0;
	int ChildCount = 0;
	std::unordered_map<char, std::shared_ptr<TrieNode>> Children;
};

std::unique_ptr<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);
}

void AddWordOccurrence(TrieNode& node, const std::string& word)
{
	if (word.empty())
	{
		node.OccurrenceCount++;
	}
	else
	{
		char currentChar = word[0];
		auto existingChild = node.Children.find(currentChar);
		if (existingChild == node.Children.end())
		{
			auto newNode = std::make_shared<TrieNode>();
			node.Children[currentChar] = newNode;
			node.ChildCount++;
			AddWordOccurrence(*newNode, word.substr(1));
		}
		else
		{
			AddWordOccurrence(*existingChild->second, word.substr(1));
		}
	}
}

bool InternalDelete(TrieNode& node, const std::string& word)
{
	if (word.empty())
	{
		node.OccurrenceCount--;
	}
	else
	{
		const char currentChar = word[0];
		auto child = node.Children[currentChar];
		if (InternalDelete(*child, word.substr(1)))
		{
			node.Children.erase(currentChar);
			node.ChildCount--;
		}
	}
	bool nodeIsDeletable = node.OccurrenceCount <= 0 && node.ChildCount <= 0;
	return nodeIsDeletable;
}

void DeleteWordOccurrence(TrieNode& node, const std::string& word)
{
	InternalDelete(node, word);
}

int CountOccurrences(TrieNode& node, const std::string& word)
{
	if (word.empty())
	{
		return node.OccurrenceCount;
	}
	const char currentChar = word[0];
	const auto child = node.Children.find(currentChar);
	if (child != node.Children.end())
	{
		return CountOccurrences(*child->second, word.substr(1));
	}
	return 0;
}

int CountLongestCommonPrefixInternal(const TrieNode& node, const std::string& word, int lengthSoFar)
{
	if (word.empty())
	{
		return lengthSoFar;
	}
	const char currentChar = word[0];
	const auto child = node.Children.find(currentChar);
	if (child != node.Children.end())
	{
		return CountLongestCommonPrefixInternal(*child->second, word.substr(1), lengthSoFar + 1);
	}
	return lengthSoFar;
}

int CountLongestCommonPrefix(const TrieNode& node, const std::string& word)
{
	return CountLongestCommonPrefixInternal(node, word, 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(*root, word);
		break;
	case('1') :
		DeleteWordOccurrence(*root, word);
		break;
	case('2') :
		printf("%d\n", CountOccurrences(*root, word));
		break;
	case('3') :
		printf("%d\n", CountLongestCommonPrefix(*root, 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);
	}
}