Cod sursa(job #724430)

Utilizator marius135Dumitran Adrian Marius marius135 Data 26 martie 2012 15:45:11
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 2.97 kb
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<string>

using namespace std;

#define maxn (1<<20)
char sir[maxn];

struct trie_node{ 
	bool final;
	int nr_sol;
	int children[26];
	vector <int> solutii;
	int fail;
	int tata;
	trie_node() {
		final = false;
		nr_sol = 0;
		fail = 0;
		memset(children, 0, sizeof(children));
	};
	
};
struct trie{ 
	vector <trie_node> nodes;
	int rad;
	trie() {
		trie_node a;
		nodes.push_back(a);
		nodes.push_back(a);
		rad = 1;
	}
	void add(char *, int);
	void complete_root();
	void fail_function();
	void run_for_word( char *, int *);
};


void trie::add( char *cuvant, int indice) {
	
	int nod_act = rad;
	string cuv(cuvant);
	int len = cuv.size();
	int i = 0;
	while( nodes[nod_act].children[cuv[i]-'a'] != 0  && i < len) {
		nod_act = nodes[nod_act].children[cuv[i]-'a'];
		i++;
	}
	for( ; i < len; ++i) {
		trie_node a;
		a.tata = nod_act;
		nodes.push_back(a);
		nodes[nod_act].children[cuv[i]-'a'] = nodes.size() - 1;
		nod_act = nodes.size() - 1;
		
	}
	nodes[nod_act].final = true;
	nodes[nod_act].nr_sol++;
	nodes[nod_act].solutii.push_back(indice);
}


void trie::complete_root() {
	for( int i = 0; i < 26; ++i) {
		if( nodes[rad].children[i] == 0)
			nodes[rad].children[i] = rad;
	}
}
void trie::fail_function() {

	queue<int> coada;
	for( int i = 0; i < 26; ++i) {
		int q = nodes[rad].children[i] ;
		if( q != rad) 
			nodes[q].fail = 1, coada.push(q);
	}
	
	while( coada.size() ) {
		int nod = coada.front();
		coada.pop();
		for( int i = 0; i < 26; ++i) {
			if( nodes[nod].children[i] == 0) continue;
			int next_nod = nodes[nod].children[i];
			coada.push(next_nod);
			int v = nodes[nod].fail;
			while( nodes[v].children[i] == 0 )
				v = nodes[v].fail;
			nodes[next_nod].fail = nodes[v].children[i];
			trie_node temp = nodes[nodes[v].children[i]];
			nodes[next_nod].nr_sol += temp.nr_sol;
			
			for( int i = 0; i< temp.solutii.size(); ++i)
				nodes[next_nod].solutii.push_back(temp.solutii[i]);
		}
	}
}

void trie::run_for_word( char *sir, int *rez) {
	int m = strlen(sir);
	int nod_act = rad;
	for( int i = 0; i < m; ++i ) {
		while(  nodes[nod_act].children[sir[i] -'a'] == 0 ) 
			nod_act = nodes[nod_act].fail;
		nod_act = nodes[nod_act].children[sir[i]-'a'];
		for( int j = 0; j < nodes[nod_act].solutii.size(); ++j)
			rez[ nodes[nod_act].solutii[j]]++;
	}
}


int main() {
	
	freopen("ahocorasick.in", "r", stdin);
	freopen("ahocorasick.out", "w", stdout);
	int nr_cuv;
	scanf("%s\n%d", sir, &nr_cuv);
	
	trie tri;
	for( int i = 0; i < nr_cuv; ++i) {
		char temp_cuv[10001];
		scanf("%s", temp_cuv);
		tri.add (temp_cuv, i);
	}
	
	tri.complete_root();
	tri.fail_function();
	
	int *rezultate = new int[nr_cuv];
	for( int i = 0; i < nr_cuv; ++i)
		rezultate[i] = 0;
	
	tri.run_for_word(sir, rezultate);
	for( int i = 0; i < nr_cuv; ++i) {
		printf("%d\n", rezultate[i]);
	}
	
	
	return 0;
}