1. 程式人生 > >poj1204(AC自動機,模板)

poj1204(AC自動機,模板)

題意:給個L*C的字串矩陣,W個詢問,對每個詢問輸出這個串第一次出現的位置及方向,共有8個方向,用A~H表示

思路:其實就是普通的AC自動機,但由於有八個方向,所以要把各種方向的可能性都給試一遍。注意,由於要記錄開始字串,所以在構造tire樹的時候就應該把那些字串倒過來構造,切記。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; 
char s[1005][1005];
char tp[1005];
int ans[1005][3],l,c,w;
struct node
{
	node *next[26],*fail;
	int fg;
	node()
	{
		fail=NULL;
		for(int i=0;i<26;i++)
		next[i]=NULL;
		fg=0;
	}
}*q[500000],*root;
int dir[8][3]={{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}};
void build_tire(node *p,int id)
{
	int t=strlen(tp);
	for(int i=t-1;i>=0;i--)
	{
		if(p->next[tp[i]-'A']==NULL)
		{
			p->next[tp[i]-'A']=new node();
		}
		p=p->next[tp[i]-'A'];
	}
	p->fg=id;
}
void make_ac(node *p)
{
	node *temp,*temp1;
	int head,tail;
	head=tail=0;
	q[tail++]=p;
	while(head!=tail)
	{
		temp=q[--tail];
		for(int i=0;i<26;i++)
		{
			if(temp->next[i]!=NULL)
			{
				if(temp==root) temp->next[i]->fail=root;
				else
				{
					temp1=temp->fail;
					while(temp1!=NULL)
					{
						if(temp1->next[i]!=NULL)
						{
							temp->next[i]->fail=temp1->next[i];
							break;
						}
						temp1=temp1->fail;
					}
					if(temp1==NULL) temp->next[i]->fail=root;
				}
				q[tail++]=temp->next[i];
			}
		}
	}	
}
void query(int x,int y,int id,int id1)
{
	node *p=root,*temp;
	while(x>=0&&y>=0&&x<l&&y<c)
	{
		
		int t=s[x][y]-'A';
		 while(p->next[t]==NULL&&p!=root) p=p->fail;
		 p=p->next[t];
		 if(p==NULL) p=root; 		 		 	
		temp=p;
		while(temp!=root)
		{
			if(temp->fg)
			{
				ans[temp->fg][0]=x;
				ans[temp->fg][1]=y;
				ans[temp->fg][2]=id1;
			}
			temp=temp->fail;
		}
		x+=dir[id][1];
		y+=dir[id][0];
	}
}
void del(node *p)
{
     if(p==NULL)return ;
     for(int i=0;i<26;i++)del(p->next[i]);
     delete p;
}
int main()
{
	//freopen("t.txt","r",stdin);
	while(scanf("%d%d%d",&l,&c,&w)!=EOF)
	{
		memset(ans,-1,sizeof(ans));
		root= new node();
		for(int i=0;i<l;i++)	{scanf("%s",s[i]);}
		for(int i=1;i<=w;i++)
		{
			scanf("%s",tp);
			build_tire(root,i);
		}
		make_ac(root);
		for(int i=0;i<l;i++)
		{
			query(i,0,1,5);
			query(i,0,2,6);
			query(i,0,3,7);
			query(i,c-1,7,3);
			query(i,c-1,6,2);
			query(i,c-1,5,1);
		}
		for(int j=0;j<c;j++)
		{
			query(l-1,j,1,5);
			query(l-1,j,0,4);
			query(l-1,j,7,3);
			query(0,j,3,7);
			query(0,j,4,0);
			query(0,j,5,1);			
		}
		for(int i=1;i<=w;i++)
		{
			char t=ans[i][2]+'A';
			printf("%d %d %c\n",ans[i][0],ans[i][1],t);
		}
		del(root);
	}
	return 0;
}