Cod sursa(job #798565)

Utilizator BlaugranasEnal Gemaledin Blaugranas Data 16 octombrie 2012 19:13:44
Problema Aho-Corasick Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 5.49 kb
#include<cstdio>
#include<cstring>
#include<cstdlib>
int i,n,b[101],j;
char s[1000005],a[101][10005],alphas[1024],alpha;

typedef struct
{char *astring,*stringy; 
int length,number;}AC_PATTERN_t;

typedef struct
{AC_PATTERN_t *patterns; 
int position,match_num;}AC_MATCH_t;

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

typedef struct node
{int final,depth;
struct node *failure_node; 
AC_PATTERN_t *matched_patterns;
int matched_patterns_num,matched_patterns_max,outgoing_degree,outgoing_max;
struct edge * outgoing;}AC_NODE_t;

typedef struct
{AC_NODE_t *root,**all_nodes,*current_node;
int all_nodes_num,all_nodes_max,automata_open,base_position,total_patterns;
AC_MATCH_t match;}AC_AUTOMATA_t;

void node_init(AC_NODE_t *thiz)
{memset(thiz,0,sizeof(AC_NODE_t));
thiz->outgoing_max=thiz->matched_patterns_max=8;
thiz->outgoing=new edge[8];
thiz->matched_patterns=new AC_PATTERN_t[8];}

void node_release(AC_NODE_t *thiz)
{free(thiz->matched_patterns);
free(thiz->outgoing);
free(thiz);}

AC_NODE_t *node_find_next(AC_NODE_t * thiz,char alpha)
{for(int i=0;i<thiz->outgoing_degree;i++)
if(thiz->outgoing[i].alpha==alpha)
    return thiz->outgoing[i].next;
return NULL;}

int node_has_matchstr (AC_NODE_t *thiz, AC_PATTERN_t *newstr)
{int i,j;
AC_PATTERN_t * str;
for(i=0;i<thiz->matched_patterns_num;i++)
	{str=&thiz->matched_patterns[i];
    if(str->length!=newstr->length)
			continue;
	for(j=0;j<str->length;j++)
	if(str->astring[j]!=newstr->astring[j])
	        continue;
	if(j==str->length)
			return 1;}
return 0;}

void node_register_outgoing(AC_NODE_t * thiz, AC_NODE_t *next,char alpha)
{if(thiz->outgoing_degree>=thiz->outgoing_max)
	{thiz->outgoing_max+=8;
	thiz->outgoing=(struct edge*)realloc(thiz->outgoing,thiz->outgoing_max*sizeof(struct edge));}
thiz->outgoing[thiz->outgoing_degree].alpha=alpha;
thiz->outgoing[thiz->outgoing_degree++].next=next;}

AC_NODE_t *node_create_next(AC_NODE_t *thiz,char alpha)
{AC_NODE_t *next=node_find_next(thiz,alpha);
if(next)
	return NULL;	
next=new AC_NODE_t;
node_init(next);
node_register_outgoing(thiz,next,alpha);
return next;}

void node_register_matchstr(AC_NODE_t *thiz,AC_PATTERN_t *str)
{if(node_has_matchstr(thiz,str))
    return;
if(thiz->matched_patterns_num>=thiz->matched_patterns_max)
	{thiz->matched_patterns_max+=8;
	thiz->matched_patterns=new AC_PATTERN_t[thiz->matched_patterns_max];}
thiz->matched_patterns[thiz->matched_patterns_num].astring=str->astring;
thiz->matched_patterns[thiz->matched_patterns_num].length=str->length;
thiz->matched_patterns[thiz->matched_patterns_num].stringy=str->stringy;
thiz->matched_patterns[thiz->matched_patterns_num++].number=str->number;}

void set_failure(AC_AUTOMATA_t *thiz,AC_NODE_t *node,char *alphas)
{int i,j;
AC_NODE_t *m;
for(i=1;i<node->depth;i++)
	{m=thiz->root;
	for(j=i;j<node->depth&&m;j++)
		m=node_find_next(m,alphas[j]);
	if(m)
		{node->failure_node=m;
		break;}}
if(!node->failure_node)
    node->failure_node=thiz->root;}
		
void traverse_setfailure(AC_AUTOMATA_t *thiz, AC_NODE_t *node,char *alphas)
{int i;
AC_NODE_t *next;
for(i=0;i<node->outgoing_degree;i++)
	{alphas[node->depth]=node->outgoing[i].alpha;
	next=node->outgoing[i].next;
	set_failure(thiz,next,alphas);
	traverse_setfailure(thiz,next,alphas);}}

void union_matchstrs(AC_NODE_t *node)
{AC_NODE_t *m=node;
while((m=m->failure_node))
   {for(int i=0;i<m->matched_patterns_num;i++)
	   node_register_matchstr(node,&(m->matched_patterns[i]));
   if(m->final)
       node->final=1;}}

void search(AC_AUTOMATA_t *thiz,char txt[])
{int position=0;
AC_NODE_t *current,*next;
if(thiz->automata_open)
      return;
current=thiz->current_node;
while(txt[position])
	  {if(!(next=node_find_next(current,txt[position])))
		    if(current->failure_node)
				current = current->failure_node;
			else
				position++;
      else
		    current=next,position++;
      if(current->final&&next)
            {thiz->match.position=position+thiz->base_position;
			thiz->match.match_num=current->matched_patterns_num;
			thiz->match.patterns=current->matched_patterns;
			for(int j=0;j<(&thiz->match)->match_num;j++)
            for(int i=0;i<n;i++)
            if(!strcmp((&thiz->match)->patterns[j].astring,a[i]))     	      
                  b[i]++;}}
thiz->current_node=current;
thiz->base_position+=position;}

int main()
{freopen("ahocorasick.in","r",stdin),freopen("ahocorasick.out","w",stdout);
gets(s),scanf("%d\n",&n);
AC_AUTOMATA_t *thiz=new AC_AUTOMATA_t;
memset(thiz,0,sizeof(AC_AUTOMATA_t));
thiz->root=new AC_NODE_t,node_init(thiz->root);
thiz->all_nodes_max=1000000;
thiz->all_nodes=new AC_NODE_t*[1000000];
thiz->all_nodes[thiz->all_nodes_num++]=thiz->root;
thiz->current_node=thiz->root;
thiz->automata_open=1;
AC_PATTERN_t tmp_patt;
for(j=0;j<n;j++)
	{gets(a[j]),tmp_patt.astring=a[j],tmp_patt.length=strlen(a[j]);
    AC_NODE_t *n=thiz->root,*next;
    for(i=0;a[j][i];i++)
	       {alpha=tmp_patt.astring[i];
           if((next=node_find_next(n,alpha)))
		         {n=next;
		         continue;}
           else
		         {next=node_create_next(n,alpha);
	             next->depth=n->depth+1,n=next;
	             thiz->all_nodes[thiz->all_nodes_num++]=n;}}
    n->final=1,node_register_matchstr(n,&tmp_patt);
    thiz->total_patterns++;}
traverse_setfailure(thiz,thiz->root,alphas);
for(i=0;i<thiz->all_nodes_num;i++)
	union_matchstrs(thiz->all_nodes[i]);
thiz->automata_open=0;
search(thiz,s);
for(i=0;i<n;i++)
     printf("%d\n",b[i]);
return 0;}