Poj 1204 简单AC自动机

题目链接:http://poj.org/problem?id=1204

 

题意:给出一个字符方阵和一系列字符串,试从方阵中找出字符串出现的位置,方阵中字符串按八个方向查询。

 

将待查询字符串插入字典树,构造AC自动机,然后对方阵的四条边,每条边对应的三个方向进行查询。

 

Code:

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define M 1024
typedef struct{
	int x,y,d;
}Result;
typedef struct talT{
	int k;
	talT *fail,*nxt[26];
}Trie;
int dir[][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
Result res[M];
char s[M][M];
char tmp[M];
int size;
Trie Memory[M<<8];
Trie *q[M<<8];
Trie *r;
int len[M];
int head,tail;
int l,c,w;

Trie *NewTrie()
{
	return &Memory[size++];
}

int Legal(int x,int y)
{
	if(x<0||x>=l) return 0;
	if(y<0||y>=c) return 0;
	return 1;
}

void Insert(char *p,int k)
{
    Trie *cur=r;
	int a;
	while(*p){
		a=*p++-'A';
		if(!cur->nxt[a])
			cur->nxt[a]=NewTrie();
		cur=cur->nxt[a];
	}
	
	cur->k=k;
}

void ACAutomation()
{
	Trie *cur,*pre;
	int i;
	head=tail=0;
	r->fail=NULL;
	q[tail++]=r;

	while(head^tail){

		cur=q[head++];

		for(i=0;i<26;i++){

			if(!cur->nxt[i]) continue;

			if(cur==r)
				cur->nxt[i]->fail=r;

			else{
				pre=cur->fail;
				while(pre&&!pre->nxt[i])
					pre=pre->fail;
				cur->nxt[i]->fail=pre?pre->nxt[i]:r;
			}
			q[tail++]=cur->nxt[i];
		}
	}
}

void ACRun(int x,int y,int d)
{
	int a;
	Trie *tmp,*cur=r;
	
	for(;Legal(x,y);x+=dir[d][0],y+=dir[d][1]){
		a=s[x][y]-'A';
		while(!cur->nxt[a]&&cur!=r)
			cur=cur->fail;
		cur=cur->nxt[a];
		if(cur==NULL) cur=r;
		tmp=cur;

		while(tmp!=r&&tmp->k){
			res[tmp->k].x=x-dir[d][0]*(len[tmp->k]-1);
			res[tmp->k].y=y-dir[d][1]*(len[tmp->k]-1);
			res[tmp->k].d=d;
			tmp->k=0;
			tmp=tmp->fail;
		}
	}
}

void ACWork()
{
	int i;
	for(i=0;i<c;i++){
		ACRun(0,i,3);ACRun(0,i,4);ACRun(0,i,5);
		ACRun(c-1,i,0);ACRun(c-1,i,1);ACRun(c-1,i,7);
	}
	for(i=0;i<l;i++){
		ACRun(i,0,1);ACRun(i,0,2);ACRun(i,0,3);
		ACRun(i,c-1,5);ACRun(i,c-1,6);ACRun(i,c-1,7);
	}
}

int main()
{
	int i;
	scanf("%d%d%d",&l,&c,&w);
	for(i=0;i<l;i++)
		scanf("%s",s[i]);
	r=NewTrie();
	for(i=1;i<=w;i++){
		scanf("%s",tmp);
		len[i]=strlen(tmp);
		Insert(tmp,i);
	}
	ACAutomation();
	ACWork();
	for(i=1;i<=w;i++)
		printf("%d %d %c\n",res[i].x,res[i].y,res[i].d+'A');
	return 0;
} 

你可能感兴趣的:(c,struct,null,insert)