Cod sursa(job #1560225)

Utilizator PatrunjeluMarginean Bogdan Alexandru Patrunjelu Data 2 ianuarie 2016 00:05:11
Problema Trie Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.76 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);
}

namespace detail
{
	bool Delete(TrieNode& node, const std::string& word, int indexInWord)
	{
		if (indexInWord == word.length())
		{
			node.OccurrenceCount--;
		}
		else
		{
			const char currentChar = word[indexInWord];
			auto child = node.Children[currentChar];
			if (Delete(*child, word, indexInWord + 1))
			{
				node.Children.erase(currentChar);
				node.ChildCount--;
			}
		}
		bool nodeIsDeletable = node.OccurrenceCount <= 0 && node.ChildCount <= 0;
		return nodeIsDeletable;
	}

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

	void AddWordOccurrence(TrieNode& node, const std::string& word, int indexInWord)
	{
		if (indexInWord == word.length())
		{
			node.OccurrenceCount++;
		}
		else
		{
			char currentChar = word[indexInWord];
			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, indexInWord + 1);
			}
			else
			{
				AddWordOccurrence(*existingChild->second, word, indexInWord + 1);
			}
		}
	}

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

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

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

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

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

void Execute(const InstructionWordPair& instructionAndWord, std::ostream& out)
{
	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') : 
		out << CountOccurrences(*root, word) << std::endl;
		break;
	case('3') :
		out << CountLongestCommonPrefix(*root, word) << std::endl;
		break;
	default: 
		break;
	}
}

int main()
{
	std::ifstream in("trie.in");
	std::ofstream out("trie.out");
	std::string line;
	while (std::getline(in, line))
	{
		auto instructionAndWord = LineToInstructionAndWord(line);
		Execute(instructionAndWord, out);
	}
	out.close();
	in.close();
}