POJ 1204 Word Puzzles // 字典树,枚举, 搜索

题目描述

POJ 1204 Word Puzzles

解题思路

题目大意:
给出一个Word Puzzles,然后询问每个单词在其中出现的坐标(i, j, dir)
i 为单词首字母的横坐标 ,j为纵坐标,dir为八方向之一(用A~H表示)

这题我一开始是将Word Puzzles所有可能的单词建Trie,然后每个单词维护(i,j,dir)的信息,这样的话时间和空间的消耗都特别巨大,因此应该换一个思路。由于查询的单词最多就1K个,因此以查询的单词来建Trie是比较合适的,然后再在Word Puzzles中枚举即可。

参考代码

//**********************************************
//  Author: @xmzyt1996
//  Date:   2015-10-21
//  Name:   POJ 1204.cpp
//**********************************************
#include <cstdio>
#include <cmath>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <bitset>
#include <vector>
#include <stack>
#include <queue>
#include <map>
using namespace std;
#define clr(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i < b; ++i)
#define per(i, a, b) for(int i = a; i >= b; --i)
#define print(x) cout << #x << " = " << x << endl
#define ps puts("debug~~")
#define all(x) (x).begin(),(x).end()
#define mp make_pair
#define pb push_back
typedef __int64 ll;
typedef pair<int, int> pii;
const double pi = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9+7;
const int MAX_N = 1010;

struct Trie {
    Trie* next[26];
    int idx;
    bool flag;
}node[MAX_N*100];

int num, rr[MAX_N], cc[MAX_N], cnt, r, c, w;
char ff[MAX_N], word[MAX_N][MAX_N], s[MAX_N];
int dir[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; // 八方向

void init () {
    num = 0;
    memset(node, 0, sizeof(node));
}

int getid (char c) { return c - 'A'; }

bool check (int i, int j) { return (i >= 0 && i < r && j >= 0 && j < c); } // 检查下标是否越界

void insert (char* s, int idx) { //将待查询单词s插入Trie中,编号为idx
    Trie* head = &node[0];
    while (*s) {
        int id = getid(*s++);
        if ((head->next[id]) == NULL)
            head->next[id] = &node[++num];
        head = head->next[id];
    }
    head->flag = 1;
    head->idx = idx;
}

void search (int i, int j, int k) { // 以Word Puzzles[i][j]为起点,方向为k(0~7) 开始搜索
    Trie* head = &node[0];
    int x = i, y = j;
    while (check(x, y)) {
        int id = getid(word[x][y]);
        head = head->next[id];
        if (head == NULL) return ;
        if (head->flag) {
            int idx = head->idx;
            rr[idx] = i, cc[idx] = j;
            ff[idx] = k + 'A';
            cnt++; head->flag = 0; // 找到之后记得去掉标记,防止重复查找
        }
        x += dir[k][0], y += dir[k][1];
    }
}

void work () {
    rep(i, 0, r) rep(j, 0, c) rep(k, 0, 8) { // 枚举Word Puzzles
        search(i, j, k);
        if (cnt == w) return ; // w个单词全部找到,可以return了
    }
}

int main() {
    scanf("%d %d %d", &r, &c, &w);
    rep(i, 0, r) scanf("%s", word[i]);
    init();
    rep(i, 0, w) {
        scanf("%s", s);
        insert(s, i);
    }
    work();
    rep(i, 0, w) printf("%d %d %c\n", rr[i], cc[i], ff[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值