Cod sursa(job #2322438)

Utilizator paul_danutDandelion paul_danut Data 17 ianuarie 2019 19:43:08
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.71 kb
#include <memory>
#include <vector>
#include <sstream>
#include <algorithm>
#include <queue>
#include <fstream>

struct Node {
	Node() : children(130, NULL)
	{
		failNode = NULL;
	};

	std::vector<Node*> children;
	std::vector<int> words;
	Node* failNode;
};

void addWordToTree(Node* currentNode, char word[], unsigned int index)
{
	char ch;
	unsigned int i = 0;
	while (word[i] != 0)
	{
		ch = word[i];

		if (currentNode->children[ch] == NULL)
		{
			currentNode->children[ch] = new Node;
		}

		currentNode = currentNode->children[ch];

		++i;
	}

	currentNode->words.push_back(index);
}

void assignFailNode(Node* root, Node* node, unsigned int ch)
{
	Node* currentNode = node;

	while (root != currentNode)
	{
		currentNode = currentNode->failNode;
		if (NULL != currentNode->children[ch])
		{
			node->children[ch]->failNode = currentNode->children[ch];
			currentNode = root;
		}
	}

	if (NULL == node->children[ch]->failNode)
	{
		node->children[ch]->failNode = root;
	}

	Node* child = node->children[ch];

	child->words.insert(child->words.end(),
						child->failNode->words.begin(),
						child->failNode->words.end());
}

void linkFailNodes(Node* root)
{
	root->failNode = root;

	std::queue<Node*> q;

	for (unsigned int i = 0; i < 130; ++i)
	{
		if (root->children[i] != NULL)
		{
			root->children[i]->failNode = root;
			q.push(root->children[i]);
		}
	}

	Node* currentNode = NULL;
	while (!q.empty())
	{
		currentNode = q.front();
		q.pop();

		for (unsigned int i = 0; i < 130; ++i)
		{
			if (NULL != currentNode->children[i])
			{
				assignFailNode(root, currentNode, i);
				q.push(currentNode->children[i]);
			}
		}
	}
}

void processText(Node *root, char text[], unsigned int frequence[])
{
	Node* currentNode = root;

	char ch;
	unsigned int i = 0;
	while (text[i] != 0)
	{
		ch = text[i];
		while (currentNode->children[ch] == NULL && currentNode != root)
		{
			currentNode = currentNode->failNode;
		}

		if (currentNode->children[ch] != NULL)
		{
			currentNode = currentNode->children[ch];

			for (const auto& word : currentNode->words)
			{
				++frequence[word];
			}
		}
		++i;
	}
}

char text[1000001];
char word[10001];
unsigned int frequence[101];
unsigned int n;

int main()
{
	Node* root = new Node;

	std::ifstream fin("ahocorasick.in");
	std::ofstream fout("ahocorasick.out");

	fin >> text;
	fin >> n;
	unsigned int index = 0;
	while (!fin.eof())
	{
		fin >> word;
		addWordToTree(root, word, index);
		++index;
	}

	linkFailNodes(root);

	processText(root, text, frequence);

	for (unsigned int i = 0; i < n; ++i)
	{
		fout << frequence[i] << '\n';
	}

	return 0;
}