Cod sursa(job #865134)

Utilizator mika17Mihai Alex Ionescu mika17 Data 26 ianuarie 2013 01:55:05
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 2.03 kb
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <queue>

class Matcher {

	struct Node {
		const static int SIGMA = 26;
		Node* g[SIGMA];
		Node* f;
		std::vector< int > o;
		Node() {
			memset(g,0,sizeof(g));
		}
	};

	Node * r;
	std::vector <std::string> dict;

public:
	Matcher(std::vector <std::string> & dict) {

		this->r = new Node();
		this->dict = dict;

		for(int i=0;i<(int)dict.size();++i) {

			Node * t = r;
			for(int j=0;j<(int)dict[i].size();++j) {
				if(t->g[ dict[i][j] - 'a' ] == NULL) {
					t->g[ dict[i][j] - 'a' ] = new Node();
				}
				t = t->g[ dict[i][j] - 'a' ];
			}

			t->o.push_back( i );
		}

		for(int i=0;i<Node::SIGMA;++i)
			if(r->g[i] == NULL)
				r->g[i] = r;

		std::queue<Node*> Q;
		
		this->r->f = NULL;

		for(int i=0;i<Node::SIGMA;++i) {
			if(r->g[i] != r) {
				Q.push(r->g[i]);
				r->g[i]->f = r;
			}
		}

		while(!Q.empty()) {
			Node * t = Q.front();
			Q.pop();

			for(int i=0;i<Node::SIGMA;++i) {
				if(t->g[i] != NULL) {
					Node* tmp = t->f;
					while(tmp->g[i] == NULL) 
						tmp = tmp->f;
					tmp = tmp->g[i];
					t->g[i]->f = tmp;
					t->g[i]->o.insert(t->g[i]->o.end(),tmp->o.begin(),tmp->o.end());
					Q.push(t->g[i]);
				}
			}
		}
	}

	bool match(std::string & str,std::vector<int> &res) {
		res = std::vector<int>(dict.size(),0);
		
		Node *t = r;
		for(int i=0;i<(int)str.size();++i) {
			while(t->g[str[i] - 'a'] == NULL)
				t = t->f;
			t = t->g[str[i] - 'a'];
			for(int j=0;j<(int)t->o.size();++j) {
				res[ t->o[j]  ] ++;
			}
		}

		return res.size() > 0;
	}
};

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

	std::string A; fin >> A;

	int M; fin >> M;
	std::vector< std::string > dict;
	while(M--)
	{
		std::string tmp; fin >> tmp; dict.push_back(tmp);
	}

	std::vector<int> res;
	if(Matcher(dict).match(A,res))
	{
		for(int i=0;i<(int)res.size();++i) {
			fout<<res[i]<<std::endl;
		}
	}
	return 0;
}