[poj] 1204 Word Puzzles || AC自动机

原题

给个X*Y的字符串矩阵,W个询问,对每个询问输出这个串出现的位置及方向,共有8个方向,顺时针开始分别用A~H表示

AC自动机的板子题。
对于待匹配串建一个自动机,然后从矩阵的四周分别沿八个方向跑,找到一个串的时候就记录答案,但不能退出。

另:方向要找好啊!!

#include<cstdio>
#include<cstring>
#define N 1010
using namespace std;
int x,y,n,ansx[N],ansy[N],d[N],l[N];
//int dx[10]={0,0,1,1,1,0,-1,-1,-1},dy[10]={0,1,1,0,-1,-1,-1,0,1};
int dx[10]={0,-1,-1,0,1,1,1,0,-1},dy[10]={0,0,1,1,1,0,-1,-1,-1};
char t[N][N],s[N],r[10]=" ABCDEFGH";
struct hhh
{
    int data;
    hhh *child[26],*fail;
    hhh()
	{
	    fail=NULL;
	    data=0;
	    for (int i=0;i<26;i++) child[i]=NULL;
	}
};
hhh *root=new hhh;
hhh *now,*tmp;
hhh* q[100*1000+10];

void add(int x)
{
    now=root;
    for (int i=1;i<=l[x];i++)
    {
	if (now->child[s[i]-'A']==NULL)
	    now->child[s[i]-'A']=new hhh;
	now=now->child[s[i]-'A'];
    }
    now->data=x;
}

void bfs()
{
    int l=0,r=0;
    root->fail=root;
     for (int i=0;i<26;i++)
    {
	if (root->child[i]==NULL)
	    root->child[i]=root;
	else
	    root->child[i]->fail=root,q[r++]=(root->child[i]);
    }
    while (r!=l)
    {
	hhh* nw=q[l++];
	for (int i=0;i<26;i++)
	{
	    if (nw->child[i])
	    {
		now=nw->child[i];
		if (now!=root) q[r++]=now;
		if (now->fail==NULL) now->fail=nw->fail->child[i];
	    }
	    else nw->child[i]=nw->fail->child[i];
	    if (nw->data==0 && nw->fail->data)
		nw->data=nw->fail->data;
	}
    }
}

void find(int a,int b,int i)
{
    now=root;
    while (1)
    {
	if (a<=0 || a>x) break;
	if (b<=0 || b>y) break;
	now=now->child[t[a][b]-'A'];
	tmp=now;
	while (tmp->data)
	{
	    int tp=tmp->data;
	    ansx[tp]=a-dx[i]*(l[tp]-1);
	    ansy[tp]=b-dy[i]*(l[tp]-1);
	    d[tp]=i;
	    tmp=tmp->fail;
	}
	a+=dx[i];
	b+=dy[i];
    }
}

int main()
{
    scanf("%d%d%d",&x,&y,&n);
    for (int i=1;i<=x;i++)
	scanf("%s",t[i]+1);
    for (int i=1;i<=n;i++)
    {
	scanf("%s",s+1);
	l[i]=strlen(s+1);
	add(i);
    }
    bfs();
    for (int i=1;i<=8;i++)
    {
	for (int j=1;j<=x;j++)
	{
	    find(j,1,i);
	    find(j,y,i);
	}
	for (int j=1;j<=y;j++)
	{
	    find(1,j,i);
	    find(x,j,i);
	}
    }
    for (int i=1;i<=n;i++)
	printf("%d %d %c
",ansx[i]-1,ansy[i]-1,r[d[i]]);
    return 0;
}
原文地址:https://www.cnblogs.com/mrha/p/7992162.html