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

Posted Mrha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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\n",ansx[i]-1,ansy[i]-1,r[d[i]]);
    return 0;
}

以上是关于[poj] 1204 Word Puzzles || AC自动机的主要内容,如果未能解决你的问题,请参考以下文章

[POJ 1204]Word Puzzles(Trie树暴搜&amp;AC自己主动机)

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

POJ 1204 Word Puzzles | AC 自动鸡

POJ 1204 Word Puzzles AC自己主动机题解

POJ - 1204

POJ 1204 AC自动机