Cod sursa(job #663593)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 18 ianuarie 2012 18:56:27
Problema Aho-Corasick Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.19 kb
#include<fstream>
#include<vector>
#define NMAX 10024
#define CH(a) a-'a'
using namespace std;
vector <int> sol[NMAX];
struct Trie{int inf;
			Trie *fiu[26],*fail;};
inline void seT_Trie(Trie *nod) {
	int i;
	nod->inf=0;
	nod->fail=0;
	for(i=0;i<26;i++)
		nod->fiu[i]=0;
}
struct w{Trie *nod;}deque[NMAX*NMAX];
Trie *T=new Trie;
char A[NMAX*100];
int n,ord,SOL[NMAX];

void afis() {
	int i;
	ofstream out("ahocorasick.out");
	for(i=1;i<=n;i++)
		out<<SOL[i]<<'\n';
	out.close();
}
void addtoSol(int k) {
	int i;
	for(i=0;i<sol[k].size();i++)
		SOL[sol[k][i]]++;
}
void solve() {
	int i;
	Trie *nod=T;
	for(i=0;i<A[i];i++) {
		while(!nod->fiu[CH(A[i])]&&nod!=T)
			nod=nod->fail;
		if(nod->fiu[CH(A[i])])
			nod=nod->fiu[CH(A[i])];
		if(nod->inf)
			addtoSol(nod->inf);
		}
}
void calc_fail() {
	int i,nr=0,j;
	Trie *nod,*p;
	T->fail=T;
	for(i=0;i<26;i++)
		if(T->fiu[i]) {
			deque[nr++].nod=T->fiu[i];
			T->fiu[i]->fail=T;
			}
	for(i=0;i<nr;i++) {
		nod=deque[i].nod;
		for(j=0;j<26;j++) {
			p=nod;
			if(nod->fiu[j]) {
				while(p!=T) {
					if(p->fail->fiu[j]) {
						nod->fiu[j]->fail=p->fail->fiu[j];
						break;
						}
					else
						p=p->fail;
					}
				p=nod->fiu[j];
				if(!p->fail)
					p->fail=T;
				deque[nr++].nod=nod->fiu[j];
				if(p->fail->inf) {
					if(!p->inf) {
						p->inf=++ord;
						sol[ord].insert(sol[ord].end(),sol[p->fail->inf].begin(),sol[p->fail->inf].end());
						}
					else
						sol[p->inf].insert(sol[p->inf].begin(),sol[p->fail->inf].begin(),sol[p->fail->inf].end());
					}
				}
			}
		}
}
void citire() {
	int i,j;
	char cuv[1024];
	Trie *nod;
	ifstream in("ahocorasick.in");
	in.getline(A,NMAX*100-2);
	seT_Trie(T);
	in>>n;
	in.getline(cuv,2);
	for(i=0;i<n;i++) {
		in.getline(cuv,1010);
		nod=T;
		for(j=0;j<cuv[j];j++) {
			if(nod->fiu[CH(cuv[j])]==0) {
				nod->fiu[CH(cuv[j])]=new Trie;
				seT_Trie(nod->fiu[CH(cuv[j])]);
				}
			nod=nod->fiu[CH(cuv[j])];
			}
		++ord;
		if(!nod->inf) {
			nod->inf=ord;
			sol[ord].push_back(ord);
			}
		else
			sol[nod->inf].push_back(ord);
		}
	in.close();
}
int main() {
	citire();
	calc_fail();
	solve();
	afis();
	return 0;
}