POJ --1204--Word Puzzle

题目大意:给出一个字符矩阵,在给出r个单词,找出这些单词在矩阵中出现的坐标和方向

由于数据规模的关系,直接搜索肯定是不行滴,。借助TRIE数据结构可以过掉,具体思路:枚举矩阵中的每一个位置和每一个方向,如果从该方向搜下去的字符出现trie树中的话就继续往下,如果trie树中没有的话,就break掉

代码:写的还是蛮清楚的嘛

#include <iostream>
#include <cstring>
#define maxnode 500000
#define maxn 1020
using namespace std;
struct trie
{
    int ch[maxnode][26];
    int val[maxnode];
    int sz;
    int idx(char c)
    {
        return c-'A';
    }
    trie()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
    }
    
    void insert(char *s,int v)
    {
        int u=0,n=strlen(s);
        for(int i=0; i<n; i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
            {
                ch[u][c]=sz++;
                memset(ch[sz],0,sizeof(ch[sz]));
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    int find(char *s)
    {
        int u=0,n=strlen(s);
        for(int i=0; i<n; i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])return 0;
            u=ch[u][c];
        }
        return val[u];
    }
};
struct s_ans
{
    int x,y;
    int c;
};
int dx[]={-1,-1,0,1,1,1,0,-1};
int dy[]={0,1,1,1,0,-1,-1,-1};
s_ans ans[maxn];
char g[maxn][maxn];
char word[maxn][maxn];
int n,m,r;
trie ti;
void init()
{
    scanf("%d%d%d",&n,&m,&r);
    for(int i=0; i<n; i++)
    {
        scanf("%s",g[i]);
    }
    for(int i=1; i<=r; i++)
    {
        scanf("%s",word[i]);
        ti.insert(word[i],i);
    }
}
bool check(int x,int y)
{
    if(x>=n||x<0||y<0||y>m)return false;
    return true;
}
void get_ans(int icount,int pos,int ox,int oy)
{
    if(icount)
    {
        int u=icount;
        ans[u].x=ox;
        ans[u].y=oy;
        ans[u].c=pos;
    }
}
void cal(int sz,int x,int y,int i,int ox ,int oy)
{
    int c=ti.idx(g[x][y]);
    if(ti.ch[sz][c])
    {
        get_ans(ti.val[ti.ch[sz][c]],i,ox,oy);
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(check(nx,ny))
        cal(ti.ch[sz][c],nx,ny,i,ox,oy);
    }
}
void slove()
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            for(int k=0; k<8; k++)
            {
                cal(0,i,j,k,i,j);
            }
        }
    }
    
    for(int i=1; i<=r; i++)
    printf("%d %d %c\n",ans[i].x,ans[i].y,ans[i].c+'A');
}
int main()
{
    init();
    slove();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值