当前位置: 首页 > article >正文

poj 1204 Word Puzzles

题目来源:http://poj.org/problem?id=1204

题意:给你一个矩阵,矩阵里面存放着一些字符,问给出的字符串,是否在矩阵中,并判断在该字符串的首个字符在矩阵中的位置,以及该字符串的方向(可以看一下样例,就明白了).

正北标记为'A',东北标记为'B',类似以顺时针并按字典序标记方向,即到'H'表示西北方向。

ac自动机来做的,事实上,这个题还可以利用深搜来求解。

ac自动机比较好的参考资料:http://download.csdn.net/detail/hearthougan/7316089

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int MAXN = 1010;struct Trie_Node
{int index;Trie_Node* pNext[26];Trie_Node* pFail;Trie_Node(){index = 0;memset(pNext, NULL, sizeof(pNext));pFail = NULL;}
};Trie_Node* pRoot;
Trie_Node* Q[MAXN*100];
char Graph[MAXN][MAXN];
int row, col;int dir[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};//这一块需要注意,数组的方向跟实际坐标的方向是不一样的
int Len[MAXN], res[MAXN][3];bool IsCanGo(int x, int y)
{if(x < 0 || x >= row || y < 0 || y >= col)return false;return true;
}void Build_Trie(char* str, int id)//建立字典树
{int j, i = 0;Trie_Node* p = pRoot;while(str[i]){j = str[i++] - 'A';if(p->pNext[j] == NULL)p->pNext[j] = new Trie_Node;p = p->pNext[j];}p->index = id;
}void Build_Fail()//建立失败指针
{Trie_Node* tmp;Trie_Node* p;int qs = 0, qe = 0, i;Q[qe++] = pRoot;pRoot->pFail = NULL;while(qs < qe){tmp = Q[qs++];p = NULL;for(i = 0; i < 26; ++i){if(tmp->pNext[i] != NULL){if(tmp == pRoot)tmp->pNext[i]->pFail = pRoot;else{p = tmp->pFail;while(p != NULL){if(p->pNext[i] != NULL){tmp->pNext[i]->pFail = p->pNext[i];break;}p = p->pFail;}if(p == NULL)tmp->pNext[i]->pFail = pRoot;}Q[qe++] = tmp->pNext[i];}}}
}void Query_Trie(int x, int y, int d)//查询
{int j;Trie_Node* p = pRoot;Trie_Node* tmp;while(IsCanGo(x, y))//多模同时匹配{j = Graph[x][y] - 'A';while(p->pNext[j] == NULL && p != pRoot)//如果p是指向叶子节点,那么就找他的失败指针指向的结点p = p->pFail;p = p->pNext[j] == NULL ? pRoot : p->pNext[j];tmp = p;//所谓多模同时匹配,关键点就是在这里,每到达一个节点,就查看它的失败指针指向的节点,是否也是一个单词的结尾while(tmp != pRoot && tmp->index > 0){res[tmp->index][0] = x - Len[tmp->index]*dir[d][0];//模式串所在位置的横、纵坐标res[tmp->index][1] = y - Len[tmp->index]*dir[d][1];res[tmp->index][2] = d;//搜寻的方向tmp->index = 0;tmp = tmp->pFail;}x = x + dir[d][0];y = y + dir[d][1];}
}void Delete_Trie(Trie_Node* p)
{int i;Trie_Node* tmp = p;for(i = 0; i < 26; ++i)if(tmp->pNext[i])Delete_Trie(tmp->pNext[i]);delete tmp;
}int main()
{int subnum, i, j;char str[MAXN];while(~scanf("%d %d %d", &row, &col, &subnum)){pRoot = new Trie_Node;memset(res, 0, sizeof(res));for(i = 0; i < row; ++i)scanf("%s", Graph[i]);for(i = 1; i <= subnum; ++i){scanf("%s", str);Len[i] = strlen(str)-1;Build_Trie(str, i);}Build_Fail();for(i = 0; i < row; ++i)//按每一行的字符串进行匹配{for(j = 0; j < 8; ++j){Query_Trie(i, 0, j);//正着扫一下Query_Trie(i, col-1, j);//反着扫一下}}for(i = 0; i < col; ++i){for(j = 0; j < 8; ++j){Query_Trie(0, i, j);Query_Trie(row-1, i, j);}}for(i = 1; i <= subnum; ++i)printf("%d %d %c\n", res[i][0], res[i][1], res[i][2]+'A');Delete_Trie(pRoot);}return 0;
}


http://www.lryc.cn/news/2412598.html

相关文章:

  • 测试基础---测试用例01
  • 1350. 院系无效的学生 1355. 活动参与者 1369. 获取最近第二次的活动 1378. 使用唯一标识码替换员工ID1398. 购买了产品 A 和产品 B 却没有购买产品 C 的顾客
  • eCharts基础详解
  • Vscode 配置C/C++开发环境
  • 我用两个月时间,终于把CSDN付费资源项目玩明白了!
  • AVR单片机网址推荐 .
  • 经典智力题
  • Selenium + Webdriver 学习(六) 自动选择、检查下拉列表
  • smplayer 中文字幕乱码,进度条及拖放MKV
  • 四年背的单词 笔记目录
  • KVM 虚拟化详解
  • nrf52832 sdk15.2.0 dfu升级攻略
  • SanDisk U盘加密软件 在其他u盘使用
  • springboot笔记整理(超详细,手把手教程!)
  • 真正的RISC-V开发板——VEGA织女星开发板开箱评测
  • ROS学习笔记-安装、环境搭建、初步体验与基本包命令
  • 2020-12-21细雨算法2.0解读
  • 一款免费无限制的AI视频生成工具火了!国内无障碍访问!目前真正免费无限制,可以用来制作抖音短视频,视频效果体验不逊色于pika和runway,以及其他的免费AI在线人工智能大模型, 附教程
  • 计算机专业毕业设计题目大全——各种类型系统设计大全
  • 磁盘分区格式FAT32与NTFS
  • 网络入门基础(网络布线)
  • 2017 我的第一篇个人博客
  • 移动网络为什么“慢”? 腾讯工程师分享弱联网优化之道
  • 卷上天!上海交大博士应聘中学保健员 复旦附中回应
  • 大学操作系统课程笔记
  • 渗透利器Weevely之奇淫技巧篇
  • 大学英语四级考试大纲
  • 高仿富途牛牛-组件化(三)-界面美化
  • QQ快速登录实现原理分析之localhost.ptlogin2.qq.com 怎么会映射到 127.0.0.1问题
  • 学编程需要哪些入门标准?(非常详细)零基础入门到精通,收藏这一篇就够了