poj 1204 AC自动机

12 篇文章 0 订阅

最直观的想法是8*(n*n)*n*n暴力

由于在表里面要朝8个方向走,不能在上面建自动机,所以要在pattern建自动机

建好后,在原表上朝8个方向走遍历整个表,这时候复杂度是8*n*n

比较慢,但觉得比较直观

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define sigma_size 26
#define N 1010
struct Node
{
    int idx;
    Node *fail;
    Node* nxt[sigma_size];
    Node()
    {
        idx=0;fail=NULL;
        memset(nxt,NULL,sizeof(nxt));
    }
};
void _insert(char *s,Node *root,int idx)
{
    for(int i=0;s[i]!='\0';++i)
    {
        if(root->nxt[s[i]-'A']==NULL)
            root->nxt[s[i]-'A']=new Node();
        root=root->nxt[s[i]-'A'];
    }
    root->idx=idx;
}
Node*q[1001000];
void getfail(Node *root)
{
    int head=0,tail=0;
    q[tail++]=root;
    root->fail=NULL;
    while(head<tail)
    {
        Node *u=q[head++];
        for(int i=0;i<sigma_size;++i)
            if(u->nxt[i])
        {
            if(u==root)
                u->nxt[i]->fail=root;
            else
            {
                Node *p=u->fail;
                while(p!=NULL&&p->nxt[i]==NULL) p=p->fail;
                u->nxt[i]->fail= p==NULL?root:p->nxt[i];
            }
            q[tail++]=u->nxt[i];
        }
    }
}
int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
int ansx[N],ansy[N],ansz[N];
char mat[N][N],temp[N];
char T[N][N];
int L,C,W;
Node *root;
void dfs(int row,int col,int d,Node *u)
{
    //if(u->idx==1||u->idx==2)
        //cout<<'d';

    if(u->idx)
    {
        /*ansx[u->idx]=row;
        ansy[u->idx]=col;
        ansz[u->idx]=d;*/
        Node *p=u;
        while(p!=NULL)
        {
            if(p->idx)
            {
                ansx[p->idx]=row;
                ansy[p->idx]=col;
                ansz[p->idx]=d;
            }
            p=p->fail;
        }
    }
    if(row>=0&&row<L&&col>=0&&col<C);
    else return;
    if(u->nxt[mat[row][col]-'A'])
        dfs(row+dir[d][0],col+dir[d][1],d,u->nxt[mat[row][col]-'A']);
    else {
            if(u==root)
                dfs(row+dir[d][0],col+dir[d][1],d,u);
            else dfs(row,col,d,u->fail);
    }
}

int main ()
{
    while(scanf("%d%d%d",&L,&C,&W)!=EOF)
    {
        for(int i=0;i<L;++i)
            scanf("%s",mat[i]);
        root=new Node();
        for(int i=1;i<=W;++i)
        {
            scanf("%s",T[i]);
            _insert(T[i],root,i);
        }
        getfail(root);

        for(int i=0;i<L;++i)
            for(int j=0;j<C;++j)
            if(i==0||i==L-1||j==0||j==C-1)
            {
                for(int d=0;d<8;++d)
                    dfs(i,j,d,root);
            }

        for(int i=1;i<=W;++i)
        {
            int rev=(ansz[i]+4)%8;
            int tt=strlen(T[i]);
            for(int j=1;j<=tt;++j)
            {
                ansx[i]+=dir[rev][0];
                ansy[i]+=dir[rev][1];
            }
            ansz[i]+='A';

            printf("%d %d %c\n",ansx[i],ansy[i],ansz[i]);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值