Cod sursa(job #798652)

Utilizator BlaugranasEnal Gemaledin Blaugranas Data 16 octombrie 2012 21:15:57
Problema Aho-Corasick Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.94 kb
#include<cstdio>
#include<cstring>
int i,n,b[101],j,k;
char s[1000005],a[101][10005],c[1024];

typedef struct
{char *a,*y; 
int l,r;}P_t;

struct edge
{char alpha;
struct node *next;};

typedef struct node
{int f,d,mpn,od;
struct node *fn; 
P_t *mp;
struct edge *o;}N_t;

typedef struct
{N_t *root,**an;
int ann;}A_t;

N_t *find_next(N_t * thiz,char alpha)
{for(int i=0;i<thiz->od;i++)
if(thiz->o[i].alpha==alpha)
    return thiz->o[i].next;
return NULL;}

int has_matchstr(N_t *thiz,P_t *newstr)
{int i,j;
P_t *str;
for(i=0;i<thiz->mpn;i++)
	{str=&thiz->mp[i];
    if(str->l!=newstr->l)
			continue;
	for(j=0;j<str->l;j++)
	if(str->a[j]!=newstr->a[j])
	        continue;
	if(j==str->l)
			return 1;}
return 0;}

N_t *create_next(N_t *thiz,char alpha)
{N_t *next=find_next(thiz,alpha);
if(next)
	return NULL;	
next=new N_t;
memset(next,0,sizeof(N_t));
next->o=new edge[8];
next->mp=new P_t[8];
thiz->o[thiz->od].alpha=alpha;
thiz->o[thiz->od++].next=next;
return next;}

void set_failure(A_t *thiz,N_t *node,char *alphas)
{N_t *m;
for(int i=1;i<node->d;i++)
	{m=thiz->root;
	for(int j=i;j<node->d&&m;j++)
		m=find_next(m,alphas[j]);
	if(m)
		{node->fn=m;
		break;}}
if(!node->fn)
    node->fn=thiz->root;}
		
void traverse_setfailure(A_t *thiz,N_t *node,char *alphas)
{N_t *next;
for(int i=0;i<node->od;i++)
	{alphas[node->d]=node->o[i].alpha;
	next=node->o[i].next;
	set_failure(thiz,next,alphas);
	traverse_setfailure(thiz,next,alphas);}}

void union_matchstrs(N_t *node)
{for(N_t *m=node;(m=m->fn);)
   {for(int i=0;i<m->mpn;i++)
   if(!has_matchstr(node,&m->mp[i]))
       node->mp[node->mpn++]=m->mp[i];   
   if(m->f)
       node->f=1;}}

int main()
{freopen("ahocorasick.in","r",stdin),freopen("ahocorasick.out","w",stdout);
gets(s),scanf("%d\n",&n);
A_t *thiz=new A_t;
memset(thiz,0,sizeof(A_t));
thiz->root=new N_t;
memset(thiz->root,0,sizeof(N_t));
thiz->root->o=new edge[8];
thiz->root->mp=new P_t[8];
thiz->an=new N_t*[1000000];
thiz->an[thiz->ann++]=thiz->root;
P_t tmp_patt;
N_t *r,*next;
for(j=0;j<n;j++)
	{gets(a[j]),tmp_patt.a=a[j],tmp_patt.l=strlen(a[j]);
    r=thiz->root;
    for(i=0;a[j][i];i++)
    if((next=find_next(r,a[j][i])))
           r=next;
    else
           {next=create_next(r,a[j][i]);
           next->d=r->d+1,r=next;
           thiz->an[thiz->ann++]=r;}
    if(!has_matchstr(r,&tmp_patt))
           r->mp[r->mpn++]=tmp_patt;
    r->f=1;}
traverse_setfailure(thiz,thiz->root,c);
for(i=0;i<thiz->ann;i++)
	union_matchstrs(thiz->an[i]);
while(s[k])
	  {if(!(next=find_next(thiz->root,s[k])))
		    if(thiz->root->fn)
				thiz->root=thiz->root->fn;
			else
				k++;
      else
		    thiz->root=next,k++;
      if(thiz->root->f&&next)
            {for(j=0;j<thiz->root->mpn;j++)
            for(i=0;i<n;i++)
            if(!strcmp(thiz->root->mp[j].a,a[i]))     	      
                  b[i]++;}}
for(i=0;i<n;i++)
     printf("%d\n",b[i]);
return 0;}