Cod sursa(job #1595774)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 10 februarie 2016 15:29:45
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.85 kb
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <array>
using namespace std;

constexpr int maxlen = 10010;

constexpr int code(const char ch){
	return ch - 'a'; }

struct nod{
	nod *tata = nullptr, *suffix = nullptr;
	array<nod*, 26> fii = {};
	int nr_pass = 0, ch; };

nod* add_child(nod *n, const char ch, vector<nod*>& layer){
	if(n->fii[code(ch)] != nullptr){
		return n->fii[code(ch)]; }

	nod *f = new nod;
	f->tata = n;
	f->ch = code(ch);
	layer.push_back(f);
	n->fii[code(ch)] = f;

	return f; }

nod* add_string(nod* n, const string& str, vector<vector<nod*>>& layers){
	for(int i = 0; i < str.size(); ++i){
		n = add_child(n, str[i], layers[i+1]); }
	return n; }

void decide_suffix(nod* n){
	// presupunem ca n nu e in primele doua layer-uri
	nod *i = n->tata->suffix;
	for( ; i->fii[n->ch] == nullptr && i->tata != nullptr; i = i->suffix);
	if(i->fii[n->ch] != nullptr){
		i = i->fii[n->ch]; }
	n->suffix = i; }

void parcurge(const string& str, nod *n){
	for(const auto ch : str){
		const auto x = code(ch);
		for( ; n->fii[x] == nullptr && n->tata != nullptr; n = n->suffix);
		if(n->fii[x] != nullptr){
			n = n->fii[x]; }
		++n->nr_pass; } }

int main(){
	ifstream f("ahocorasick.in");
	ofstream g("ahocorasick.out");

	string str;
	f >> str;

	int n;
	f >> n;

	vector<nod*> rez(n, nullptr);

	vector<vector<nod*>> layers(maxlen);

	nod *rad = new nod;

	for(int i = 0; i < n; ++i){
		string tmp;
		f >> tmp;

		rez[i] = add_string(rad, tmp, layers); }

	rad->suffix = rad;

	for(const auto x : layers[1]){
		x->suffix = rad; }

	for(int i = 2; i < maxlen; ++i){
		for(const auto x : layers[i]){
			decide_suffix(x); } }

	parcurge(str, rad);

	for(int i = maxlen-1; i > 0; --i){
		for(const auto x : layers[i]){
			x->suffix->nr_pass += x->nr_pass; } }

	for(const auto x : rez){
		g << x->nr_pass << endl; }

	return 0; }