字典树PKU 1204 Word Puzzles

PKU 1204 Word Puzzles

题目的大意为:

要求编程实现查找字谜拼图中的单词,输出查找到的单词的起始位置和方向(ABCDEFGH分别代表北、东北、东、东南、南、西南、西、西北八个方向)。

输入:

输入的第一行包含三个正数:行数,0<L<=1000;列数,0<C<= 1000;和字谜单词个数0<W<=1000。接下来的L行,每行输入C个字符。最后W行每行输入一个字谜单词。

输出:

你的程序应该每行输出每个单词(跟输入的顺序相同)第一个字母出现的行和列的下标。在三个值之间必须是一个空间分隔。

解题思路:

此题涉及到单词字符串的查找匹配,为了提高查找效率,减少空间耗费,可以考虑使用字典树,字典树的优点是能利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。

字典树的根节点不包含字符,除根节点外每一个节点都只包含一个字符; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同。

针对该题,可以设计一个26个大写字母的字典树,结点结构为:

struct Node{

int index;//字符串结尾标志,单词的序号,初始化为-1

Node* next[26];//指向26个子树的指针数组,初始化为null

};

此处用到的操作有插入,查找;

字典树插入字符串的方法为:

(1)从根结点的子结点开始插入的字符串的第一字符,(若该子结点为空,创建该结点),并将该结点作为下一个字符的父结点。

(2)迭代到下一个字符,直至字符串全部插入。

(3)在字符串最后一个字母的结点标记该字符串的序号,方便查找。

搜索字典项目的方法为:

(1) 从根结点开始一次搜索;

(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;

(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。

(4) 迭代过程……

(5) 在某个结点处,关键词的所有字母已被取出(index非负),即完成查找,若结点为空,查找失败。

例如:往一棵空树中插入序列:YES,假设该字符串的序号index为2

代码:

#include<stdio.h>
#include <memory.h>
#define MaxNode 26//子结点数量
char puzzle[1001][1001];
//A...H的8个方向
int D[8][2] = { { -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 },
{ 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 } };
struct {
	int x;
	int y;
	char dir;
}outputList[1001];//记录单词位置和方向的数组
struct TrieNode{//结点结构
public:
	int wordIndex;//单词序号
	TrieNode* next[MaxNode];//26个字母的子结点指针
	TrieNode(){//构造函数
		wordIndex = -1;
		memset(next, NULL, sizeof(TrieNode*)*MaxNode);
	}
};
class Trie{//字典树
public:
	int MaxRow, MaxCol, MaxWords;
	Trie()
	{
		root = new TrieNode();
	};
	int find(int i, int j,char dir)//从i行,j列沿dir方向查找
	{
		int pos = puzzle[i][j] - ‘A‘;
		int x = i,y = j;
		TrieNode* current = root->next[pos];
			while (current != NULL)
			{
				if (current->wordIndex > 0)//找到单词,记录单词位置和方向
				{
					outputList[current->wordIndex].x = x;
					outputList[current->wordIndex].y = y;
					outputList[current->wordIndex].dir = (char)dir + ‘A‘;;
				}
				i += D[dir][0]; j += D[dir][1];//dir方向的下一个字母的下标
				if (i < 0||j<0||i>=MaxRow||j>=MaxCol)break;//超出puzzle图则跳出循环
				pos = puzzle[i][j] - ‘A‘;
				current = current->next[pos];//指向下一个字典树结点
			}
		return -1;
	};
	void insert(char *des,int index)//插入序号为index的字符串des
	{
		TrieNode* current = root;//从根结点开始
		int pos;
		for (; *des!=‘\0‘; des++)//将每个字符插入
		{
			pos = *des - ‘A‘;
			if (current->next[pos] == NULL)
				current->next[pos] = new TrieNode();//结点为空则创建
			current = current->next[pos];
		}
		current->wordIndex = index;//插入结束,标记该字符串序号
	};
private:
	TrieNode * root;//树根指针
};
int main()
{
	Trie T;
	scanf("%d%d%d", &T.MaxRow, &T.MaxCol, &T.MaxWords);
	getchar();//去掉换行符
		for (int i = 0; i < T.MaxRow; i++)
		{
			gets(puzzle[i]);
		}
		char t[1001];
		for (int i = 1; i <= T.MaxWords; i++)
		{
			gets(t);
			T.insert(t,i);
		}
		for (int i = 0; i < T.MaxRow; i++)
		for (int j = 0; j < T.MaxCol; j++)
		{
			for (int dir = 0; dir <= 7; dir++)
			{
				T.find(i, j, dir);
			}
		}
		for (int i = 1; i <= T.MaxWords; i++)
		{
			printf("%d %d %c\n", outputList[i].x, outputList[i].y, outputList[i].dir);
		}
	return 0;
}

  

时间: 2024-11-06 04:48:43

字典树PKU 1204 Word Puzzles的相关文章

[POJ 1204]Word Puzzles(Trie树暴搜)

Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using table covers with word puzzles printed on them, possibly with the intent to minimise their client's percepti

【POJ】1204 Word Puzzles

这道题目各种wa.首先是错了一个坐标,居然没测出来.然后是剪枝错误.搜索pen时就返回,可能还存在串pen*. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 #define MAXN 1005 6 7 typedef struct Trie { 8 int v; 9 Trie *next[26]; 10 Trie() { 11 v = 0; 12 for (int i=0; i<

POJ 1204 Word Puzzles AC自动机题解

AC自动机的灵活运用,本题关键是灵活二字. 因为数据不是很大,时间要求也不高的缘故,所以本题有人使用暴力法也过了,有人使用Trie也过了. 当然有人使用AC自动机没AC的,在讨论区里喊AC自动机超时的,那是因为不会灵活运用,或者是硬套模板的,AC了速度也不会快. 给出本人的算法思路: 1 把需要查找的关键字建立Trie, 然后构造AC自动机 2 查找的时候分八个方向查找,比如棋盘是board[N][M],那么就可以循环i(0->N-1),然后每次把board[i]当做一个文本,做过HDU的key

poj 1204 Word Puzzles(字典树)

题目链接:http://poj.org/problem?id=1204 思路分析:由于题目数据较弱,使用暴力搜索:对于所有查找的单词建立一棵字典树,在图中的每个坐标,往8个方向搜索查找即可: 需要注意的是查找时不能匹配了一个单词就不在继续往该方向查找,因为在某个坐标的某个方向上可能会匹配多个单词,所以需要一直 查找直到查找到该方向上最后一个坐标: 代码如下: #include <cstdio> #include <cstring> #include <iostream>

POJ 1204 Word Puzzles(字典树+搜索)

题意:在一个字符矩阵中找每个给定字符串的匹配起始位置和匹配方向(A到H表示八个方向): 思路:将给定字符串插入字典树中,遍历字符矩阵,在每个字符处向八个方向用字典树找. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef struct node { int num; node *next[26]; }node; node *head; char str[1

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

Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using table covers with word puzzles printed on them, possibly with the intent to minimise their client's percepti

POJ 1204 Word Puzzles (AC自动机)

Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9926   Accepted: 3711   Special Judge Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started us

【 POJ - 1204 Word Puzzles】(Trie+爆搜)

Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10782 Accepted: 4076 Special Judge Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using t

POJ 题目1204 Word Puzzles(AC自动机,多个方向查询)

Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10244   Accepted: 3864   Special Judge Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started u