HDU1857题解(逆向思维trie)
题目link:http://acm.hdu.edu.cn/showproblem.php?pid=1857
先简述一下题目:
有一个RXC的字母矩形,R,C在500内,要匹配m个单词,m在100000内,每个单词长度不超过20,匹配方法为向右或者向下,或者右下,即三个方向,0度,90度,45度。
现在要输出:如果匹配成功,输出第一个字母的坐标,如果有多个匹配,输出最左上的,如果不成功,输出-1 -1。
如果你使用简单的匹配,或者搜索,超时无限次,如果你字母矩阵构树单词构trie树,必超内存,自己可以想想。
所以我也很无奈,这是我比赛时候遇到的一题,当时我开了这题,很无力……
这题目标志着我开始学习trie树,经过两天的思考,和参阅别人的思想,我们用逆向思维来做,以需匹配的单词构树(只有100000个),用字母矩阵来匹配,所以在插入的时候,我们给要匹配的单词编号,用RR,CC数组来记录对应单词的坐标,初始化为0(我用的是0,也可以memset( ,-1, )),之后查找的时候,就传入(行数+1,列数+1,)之所以加1,是因为想用0来表示没成功匹配。我在trie里写了terminable,id(属于第几个单词插入)属性,在查找过程,只要遇到结点terminable,就比较是否记载过,没记载过,就将RR[id],CC[id]标记为传入参数r,c。最后顺序输出即可。
想清楚后,昨晚很自信地开始拍了,经过各种调试,总算过了sample了……马上就提交了,这次终于没有TLE了,且速度十分快……在c++提交是wa,在g++提交是RE。
这时候已经很夜了,我心想,先休息吧……
每次带着问题休息,效果都会很差,想了很久,还是觉得没问题,最后在郁闷与猜疑中睡去了.
今天醒来,发现了一个很基本的错误,我的数组开得太小了……改了一下,马上就过掉了……!!!!
- #include<iostream>
- #include<cstdio>
- #include<string>
- #include<cstring>
- #include<cmath>
- #include<cstdlib>
- using namespace std;
- template<int Size>
- struct trie_node{
- bool terminable; //表示节点为字符串的结尾
- int node; //子节点的个数
- int id;
- trie_node *child[Size]; //儿子节点
- trie_node():terminable(false), node(){
- memset(child,,sizeof(child)); //初始化节点
- }
- };
- int RR[],CC[];
- template<int Size,typename Index>
- class trie{
- public:
- //定义类名
- typedef trie_node<Size> node_type;
- typedef trie_node<Size> *link_type;
- //构造函数
- trie(Index i=Index()):index(i){ }
- //清空函数,用于析构
- void clear(){
- clear_node(root);
- for(int i=;i<Size;i++)
- root.child[i]=;
- }
- //插入
- template<typename Iterator>
- void insert(Iterator begin,Iterator end,int i){
- link_type cur= &root;//当前插入结点为根
- while(begin!=end){
- if(cur->child[index[*begin]]){//插入过
- cur=cur->child[index[*begin]];
- ++(cur->node);
- }else{
- cur->child[index[*begin]]=new node_type;
- ++(cur->child[index[*begin]]->node);
- cur=cur->child[index[*begin]];
- }
- begin++; //迭代器往前走!
- }
- cur->terminable=true;
- cur->id=i;
- }
- //重载c风格插入
- void insert(const char * str,int i){
- insert(str,str+strlen(str), i);
- }
- //查找
- template <typename Iterator>
- void find(Iterator begin,Iterator end,int r,int c){
- link_type cur=&root;
- while(begin!=end){
- if(cur->terminable){
- if(RR[cur->id]==){
- RR[cur->id]=r;
- CC[cur->id]=c;
- }
- }
- if(!cur->child[index[*begin]]) //没有节点啊!!!
- return ;
- cur=cur->child[index[*begin]];
- begin++;
- }
- if( cur->terminable) {//是否为字符串
- if(RR[cur->id]==){
- RR[cur->id]=r;
- CC[cur->id]=c;
- }
- }
- }
- //重载c风格
- void find(const char *str,int r,int c){
- find(str,str+strlen(str),r,c);
- }
- private:
- //清空
- void clear_node(node_type cur){
- for(int i=;i<Size;i++){
- if(cur.child[i]==)continue; //不存在
- clear_node(*cur.child[i]);
- delete cur.childe[i];
- cur.child[i]=;
- if(--cur.node==) break; //没有节点了
- }
- }
- //根
- node_type root;
- //字符转索引,类似hash
- Index index;
- };
- class IndexClass{
- public:
- int operator[](const char key){
- return key%; //一个映射
- }
- };
- char cc[][];
- char s[];
- int mini(int a,int b){
- return a>b?b:a;
- }
- int main(){
- trie<,IndexClass> t;
- int R,C,i,j,l,ed;
- scanf("%d%d",&R,&C);
- getchar(); //读掉回车
- for( i=;i<R;i++)
- {
- gets(cc[i]);
- }
- int N=;
- while(gets(s)&&s[]!='-'){
- if(s[]){
- t.insert(s,N); //用每一个要查找的单词构树
- N++;
- }
- }
- for(i=;i<R;i++)
- for( j=;j<C;j++){
- //向下
- memset(s,,sizeof(s));
- if(i+<R) ed=;
- else ed=R-i;
- for(l=;l<ed;l++){
- s[l]=cc[i+l][j];
- }
- t.find(s,i+,j+);
- //向右
- memset(s,,sizeof(s));
- if(j+<C) ed=;
- else ed=C-j;
- for( l=;l<ed;l++){
- s[l]=cc[i][j+l];
- }
- t.find(s,i+,j+);
- //右下
- memset(s,,sizeof(s));
- if(i+<R&&j+<C) ed=;
- else ed=mini(C-j,R-i);
- for( l=;l<ed;l++){
- s[l]=cc[i+l][j+l];
- }
- t.find(s,i+,j+);
- }
- for( i=;i<N;i++){
- if(RR[i]!=||CC[i]!=)
- printf("%d %d\n",RR[i]-,CC[i]-);
- else puts("-1 -1");
- }
- return ;
- }
HDU1857题解(逆向思维trie)的更多相关文章
- tyvj1161聚会的名单(trie树)
背景 Background 明天就是candy的生日,candy又会邀请自己的一大堆好友来聚会了!哎!又要累坏飘飘乎居士了!! 描述 Description 明天就是candy的生日.晚上,c ...
- HDU1671 - Phone List(Trie树)
题目大意 给定一些电话号码,判断是否有电话号码是其他电话号码的前缀 题解 裸Trie树嘛~~~~只需要一个插入过程即可,假设X是Y的前缀,在插入的过程中有两种情况,X在Y之前插入,那么在插入Y的时候经 ...
- hiho #1014 : Trie树(模板)
Trie树 [题目链接]Trie树 &题意: 输入 输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词(不保证是英文单词,也有可能是火星文单词哦),单词由不超过10个的小写英 ...
- HDU 1251 统计难题(Trie)
统计难题 [题目链接]统计难题 [题目类型]Trie &题解: Trie的模板题,只不过这题坑点在没给数据范围,改成5e5就可以过了,用的刘汝佳蓝书模板 &代码: #include & ...
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset Trie
题目链接: http://codeforces.com/contest/706/problem/D D. Vasiliy's Multiset time limit per test:4 second ...
- 算法复习——trie树(poj2001)
题目: 题目描述 给出 n 个单词(1<=n<=1000),求出每个单词的非公共前缀,如果没有,则输出自己. 输入格式 输入 N 个单词,每行一个,每个单词都是由 1-20 个小写字母构成 ...
- hihoCoder #1014 : Trie树 [ Trie ]
传送门 #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互 ...
- CF456D A Lot of Games (字典树+DP)
D - A Lot of Games CF#260 Div2 D题 CF#260 Div1 B题 Codeforces Round #260 CF455B D. A Lot of Games time ...
- Wild Words
poj1816:http://poj.org/problem?id=1816 题意:给你n个模板串,然后每个串除了字母,还有?或者*,?可以代替任何非空单个字符,*可以替代任何长度任何串,包括空字符串 ...
随机推荐
- seajs 2.3.0 加入jquery
[前言] 上篇文章简单的介绍了seajs的使用,下午使用seajs整合jquery就碰到问题了. 下载seajs上的examples,里面直接require('jquery')没有不论什么问题, 我照 ...
- HomeSnap
http://arnauddegiuli.github.io/HomeSnap/ OnBufferingUpdateListener https://github.com/LuckyJayce/Mat ...
- MySQL Troubleshoting:Waiting on query cache mutex 腾讯数据库工程师:幕南风
http://blog.itpub.net/26515977/viewspace-1208188/ 今天被MySQL Query Cache 炕了.线上大量 Waiting on ...
- Python学习 之 函数
1.为什么要使用函数 (1)降低编程难度:将复杂的问题分解成简单的小问题 (2)代码重用 2.函数的定义 def 函数名(参数列表):#可以没有参数 函数体 3.函数缺省参数(默认参数):设置默认参数 ...
- Linux环境变量的修改(永久,暂时)
Linux修改环境变量,很简单但很重要 一.Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1. 永久的:需要修改配置文件,变量永久生效. 2. 临时的:使用export命令 ...
- BFS-hdu-1226-超级密码
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1226 题目意思: 给一个N,给nn个jj进制的数字,问最小的不超过500位的由这些数字组成的jj进制 ...
- 详解ARM的AMBA设备中的 DMA设备PL08X的Linux驱动
1. 此文目的记录笔者对ARM的PL08x的DMA驱动PL08x.c理解.给其他不熟悉此DMA驱动的读者一点借鉴和参考.2. 适合读者你已经具备一定驱动编程能力,知道一些最基本的概念,比如用于输出输出 ...
- poj 3252 Round Numbers 【推导·排列组合】
以sample为例子 [2,12]区间的RoundNumbers(简称RN)个数:Rn[2,12]=Rn[0,12]-Rn[0,1] 即:Rn[start,finish]=Rn[0,finish]-R ...
- cocos2d-x使用ant打包
1. 下载apache-ant-1.9.3,然后添加环境变量ANT_HOME = D:\dev_envir\apache-ant-1.9.3(你自己的ant根目录),再在path中添加路径:%ANT_ ...
- PHP读书笔记(3)-常量
什么是常量 什么是常量?常量可以理解为值不变的量 :或者是常量值被定义后,在脚本的其他任何地方都不可以被改变.手册上是这么定义PHP的常量:常量是一个简单值的标识符(名字).如同其名称所暗示的,在脚本 ...