POJ 1204 Word Puzzles(AC自动机)

每次找到了一个串的头,就要回去找他的前驱结点因为有可能模式串为abcd bcd如果不找前驱结点bcd的开始位置永远找不到。

//
//  main.cpp
//  Richard
//
//  Created by 邵金杰 on 16/9/2.
//  Copyright © 2016年 邵金杰. All rights reserved.
//



#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=1000000+100;
const int N=1000+10;
string map[N];
struct node{
    node *child[26];
    node *pre;
    int pos;
    bool badnode;
    void intial(){
        memset(child,0,sizeof(child));
        pos=0;
        badnode=false;
        pre=NULL;
    }
}tree[maxn];
int ncount;
pair<int,int> pa[N];
char dire[N];
string s;
int r,c,w;
const int dx[]={-1,-1,0,1,1, 1, 0,-1};
const int dy[]={ 0, 1,1,1,0,-1,-1,-1};
const char dir[]={"EFGHABCD"};
void Insert(node *p,int no)
{
    for(int i=0;s[i];i++)
    {
        if(p->child[s[i]-'A']==NULL)
        {
            p->child[s[i]-'A']=tree+ncount;
            ncount++;
        }
        p=p->child[s[i]-'A'];
    }
    p->badnode=true;
    p->pos=no;
}
void BuildDFA()
{
    for(int i=0;i<26;i++)
        tree[0].child[i]=tree+1;
    tree[0].pre=NULL;
    tree[1].pre=tree;
    queue<node*> q;
    q.push(tree+1);
    while(!q.empty())
    {
        node *proot=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            node *p=proot->child[i];
            if(p)
            {
                node *pre=proot->pre;
                while(pre)
                {
                    if(pre->child[i]!=NULL)
                    {
                        p->pre=pre->child[i];
                        break;
                    }
                    else
                        pre=pre->pre;
                }
                q.push(p);
            }
        }
    }
}
bool inside(int x,int y)
{
    return x>=0&&x<r&&y>=0&&y<c;
}
void searchDFA(int i,int j,int k)
{
    node *p=tree+1;
    int x=i,y=j;
    while(true)
    {
        if(!inside(x,y)) break;
        while(true)
        {
            if(p->child[map[x][y]-'A']!=NULL){
                p=p->child[map[x][y]-'A'];
                node *pre=p;
                while(pre->badnode) {
                    if(pre->pos){
                    pa[pre->pos].first=x;
                    pa[pre->pos].second=y;
                    dire[pre->pos]=dir[k];
                    pre->pos=0;
                    }
                    pre=pre->pre;
                }
                break;
            }
            else p=p->pre;
        }
        x+=dx[k];
        y+=dy[k];
    }
}
void work()
{
    for(int i=0;i<r;i++)
    {
        searchDFA(i,0,2);
        searchDFA(i,c-1,6);
        searchDFA(i,0,1);
        searchDFA(i,0,3);
        searchDFA(i,c-1,7);
        searchDFA(i,c-1,5);
    }
    for(int j=0;j<c;j++)
    {
        searchDFA(0,j,4);
        searchDFA(r-1,j,0);
        searchDFA(0,j,5);
        searchDFA(0,j,3);
        searchDFA(r-1,j,1);
        searchDFA(r-1,j,7);
    }
    for(int i=1;i<=w;i++)
    {
        cout<<pa[i].first<<' '<<pa[i].second<<' '<<dire[i]<<endl;
    }
}
int main()
{
    cin>>r>>c>>w;
    ncount=2;
    for(int i=0;i<r;i++)
        cin>>map[i];
    for(int i=1;i<=w;i++)
    {
        cin>>s;
        reverse(s.begin(),s.end());
        Insert(tree+1,i);
    }
    BuildDFA();
    work();
    return 0;
}




 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值