Cod sursa(job #971630)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 9 iulie 2013 19:18:02
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.54 kb

#include <fstream>
#include <string>

const int ALPHABET_SIZE('z' - 'a' + 1);
const int MAX_SIZE(1000001);
const int MAX_N(101);

struct Trie
{
	int occ = 0;
	struct Trie *node [ALPHABET_SIZE] = {nullptr};
	struct Trie *fail = nullptr;
} *Automaton;

inline void Initialise (struct Trie *&node)
{
	node = new struct Trie;
}

inline void Insert (struct Trie *&node, std::string &word)
{
	if (!node)
		Initialise(node);
	struct Trie *iterator(node);
	for (int index(0) ; index < word.size() ; ++index)
	{
		if (!iterator->node[word[index] - 'a'])
			Initialise(iterator->node[word[index] - 'a']);
		iterator = iterator->node[word[index] - 'a'];
	}
}

inline int Query (std::string word)
{
	struct Trie *iterator(Automaton);
	for (int i(0) ; i < word.size() ; ++i)
		iterator = iterator->node[word[i] - 'a'];
	return iterator->occ;
}

int n;
std::string Strings [MAX_N];
std::string s;
int Matches [MAX_N];
struct Trie *Queue [MAX_SIZE];
struct Trie **Push(Queue + 1), **Pop(Queue);

inline void Read (void)
{
	std::ifstream input("ahocorasick.in");
	input >> s;
	input >> n;
	for (int index(0) ; index < n ; ++index)
		input >> Strings[index];
	input.close();
}

inline void Print (void)
{
	std::ofstream output("ahocorasick.out");
	for (int index(0) ; index < n ; ++index)
		output << Query(Strings[index]) << '\n';
	output.close();
}

inline void Build (void)
{
	for (int index(0) ; index < n ; ++index)
		Insert(Automaton,Strings[index]);
}

inline void BreadthFirstSearch (void)
{
	Automaton->fail = Automaton;
	Queue[0] = Automaton;
	struct Trie *node, *fail;
	int i;
	while (Pop != Push)
	{
		node = *Pop;
		++Pop;
		for (i = 0 ; i < ALPHABET_SIZE ; ++i)
			if (node->node[i])
			{
				for (fail = node->fail ; fail != Automaton && !fail->node[i] ; fail = fail->fail)
					/* do nothing */;
				if (fail != node)
					fail = fail->node[i];
				if (!fail)
					fail = Automaton;
				node->node[i]->fail = fail;
				*Push = node->node[i];
				++Push;
			}
	}
}

inline void AhoCorasick (void)
{
	struct Trie *iterator(Automaton);
	for (int index(0) ; index < s.size() ; ++index)
	{
		while (!iterator->node[s[index] - 'a'] && iterator != Automaton)
			iterator = iterator->fail;
		if (iterator->node[s[index] - 'a'])
			iterator = iterator->node[s[index] - 'a'];
		++iterator->occ;
	}
}

inline void ReverseBreadthFirstSearch (void)
{
	--Pop;
	struct Trie *iterator;
	while (Pop >= Queue)
	{
		iterator = *Pop;
		iterator->fail->occ += iterator->occ;
		--Pop;
	}
}

int main (void)
{
	Read();
	Build();
	BreadthFirstSearch();
	AhoCorasick();
	ReverseBreadthFirstSearch();
	Print();
	return 0;
}