题目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。

这时候已经很夜了,我心想,先休息吧……

每次带着问题休息,效果都会很差,想了很久,还是觉得没问题,最后在郁闷与猜疑中睡去了.

今天醒来,发现了一个很基本的错误,我的数组开得太小了……改了一下,马上就过掉了……!!!!

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<string>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<cstdlib>
  7. using namespace std;
  8. template<int Size>
  9. struct trie_node{
  10.  
  11. bool terminable; //表示节点为字符串的结尾
  12. int node; //子节点的个数
  13. int id;
  14. trie_node *child[Size]; //儿子节点
  15. trie_node():terminable(false), node(){
  16. memset(child,,sizeof(child)); //初始化节点
  17. }
  18.  
  19. };
  20. int RR[],CC[];
  21. template<int Size,typename Index>
  22. class trie{
  23. public:
  24. //定义类名
  25. typedef trie_node<Size> node_type;
  26. typedef trie_node<Size> *link_type;
  27.  
  28. //构造函数
  29. trie(Index i=Index()):index(i){ }
  30.  
  31. //清空函数,用于析构
  32. void clear(){
  33. clear_node(root);
  34. for(int i=;i<Size;i++)
  35. root.child[i]=;
  36. }
  37. //插入
  38. template<typename Iterator>
  39. void insert(Iterator begin,Iterator end,int i){
  40.  
  41. link_type cur= &root;//当前插入结点为根
  42. while(begin!=end){
  43. if(cur->child[index[*begin]]){//插入过
  44. cur=cur->child[index[*begin]];
  45. ++(cur->node);
  46.  
  47. }else{
  48. cur->child[index[*begin]]=new node_type;
  49. ++(cur->child[index[*begin]]->node);
  50. cur=cur->child[index[*begin]];
  51.  
  52. }
  53.  
  54. begin++; //迭代器往前走!
  55. }
  56. cur->terminable=true;
  57. cur->id=i;
  58.  
  59. }
  60.  
  61. //重载c风格插入
  62. void insert(const char * str,int i){
  63. insert(str,str+strlen(str), i);
  64. }
  65.  
  66. //查找
  67. template <typename Iterator>
  68. void find(Iterator begin,Iterator end,int r,int c){
  69. link_type cur=&root;
  70. while(begin!=end){
  71.  
  72. if(cur->terminable){
  73.  
  74. if(RR[cur->id]==){
  75.  
  76. RR[cur->id]=r;
  77. CC[cur->id]=c;
  78. }
  79. }
  80.  
  81. if(!cur->child[index[*begin]]) //没有节点啊!!!
  82. return ;
  83.  
  84. cur=cur->child[index[*begin]];
  85.  
  86. begin++;
  87.  
  88. }
  89. if( cur->terminable) {//是否为字符串
  90.  
  91. if(RR[cur->id]==){
  92.  
  93. RR[cur->id]=r;
  94. CC[cur->id]=c;
  95. }
  96. }
  97.  
  98. }
  99.  
  100. //重载c风格
  101. void find(const char *str,int r,int c){
  102.  
  103. find(str,str+strlen(str),r,c);
  104. }
  105.  
  106. private:
  107.  
  108. //清空
  109. void clear_node(node_type cur){
  110. for(int i=;i<Size;i++){
  111. if(cur.child[i]==)continue; //不存在
  112. clear_node(*cur.child[i]);
  113. delete cur.childe[i];
  114. cur.child[i]=;
  115. if(--cur.node==) break; //没有节点了
  116.  
  117. }
  118.  
  119. }
  120.  
  121. //根
  122. node_type root;
  123. //字符转索引,类似hash
  124. Index index;
  125.  
  126. };
  127.  
  128. class IndexClass{
  129. public:
  130. int operator[](const char key){
  131. return key%; //一个映射
  132.  
  133. }
  134.  
  135. };
  136. char cc[][];
  137. char s[];
  138. int mini(int a,int b){
  139. return a>b?b:a;
  140. }
  141. int main(){
  142. trie<,IndexClass> t;
  143. int R,C,i,j,l,ed;
  144. scanf("%d%d",&R,&C);
  145. getchar(); //读掉回车
  146. for( i=;i<R;i++)
  147. {
  148.  
  149. gets(cc[i]);
  150. }
  151.  
  152. int N=;
  153. while(gets(s)&&s[]!='-'){
  154. if(s[]){
  155. t.insert(s,N); //用每一个要查找的单词构树
  156. N++;
  157. }
  158.  
  159. }
  160.  
  161. for(i=;i<R;i++)
  162. for( j=;j<C;j++){
  163. //向下
  164. memset(s,,sizeof(s));
  165. if(i+<R) ed=;
  166. else ed=R-i;
  167. for(l=;l<ed;l++){
  168. s[l]=cc[i+l][j];
  169.  
  170. }
  171.  
  172. t.find(s,i+,j+);
  173. //向右
  174. memset(s,,sizeof(s));
  175. if(j+<C) ed=;
  176. else ed=C-j;
  177. for( l=;l<ed;l++){
  178. s[l]=cc[i][j+l];
  179.  
  180. }
  181.  
  182. t.find(s,i+,j+);
  183.  
  184. //右下
  185. memset(s,,sizeof(s));
  186. if(i+<R&&j+<C) ed=;
  187. else ed=mini(C-j,R-i);
  188. for( l=;l<ed;l++){
  189. s[l]=cc[i+l][j+l];
  190.  
  191. }
  192.  
  193. t.find(s,i+,j+);
  194.  
  195. }
  196.  
  197. for( i=;i<N;i++){
  198.  
  199. if(RR[i]!=||CC[i]!=)
  200. printf("%d %d\n",RR[i]-,CC[i]-);
  201. else puts("-1 -1");
  202. }
  203.  
  204. return ;
  205.  
  206. }

HDU1857题解(逆向思维trie)的更多相关文章

  1. tyvj1161聚会的名单(trie树)

    背景 Background 明天就是candy的生日,candy又会邀请自己的一大堆好友来聚会了!哎!又要累坏飘飘乎居士了!! 描述 Description     明天就是candy的生日.晚上,c ...

  2. HDU1671 - Phone List(Trie树)

    题目大意 给定一些电话号码,判断是否有电话号码是其他电话号码的前缀 题解 裸Trie树嘛~~~~只需要一个插入过程即可,假设X是Y的前缀,在插入的过程中有两种情况,X在Y之前插入,那么在插入Y的时候经 ...

  3. hiho #1014 : Trie树(模板)

    Trie树 [题目链接]Trie树 &题意: 输入 输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词(不保证是英文单词,也有可能是火星文单词哦),单词由不超过10个的小写英 ...

  4. HDU 1251 统计难题(Trie)

    统计难题 [题目链接]统计难题 [题目类型]Trie &题解: Trie的模板题,只不过这题坑点在没给数据范围,改成5e5就可以过了,用的刘汝佳蓝书模板 &代码: #include & ...

  5. 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 ...

  6. 算法复习——trie树(poj2001)

    题目: 题目描述 给出 n 个单词(1<=n<=1000),求出每个单词的非公共前缀,如果没有,则输出自己. 输入格式 输入 N 个单词,每行一个,每个单词都是由 1-20 个小写字母构成 ...

  7. hihoCoder #1014 : Trie树 [ Trie ]

    传送门 #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互 ...

  8. 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 ...

  9. Wild Words

    poj1816:http://poj.org/problem?id=1816 题意:给你n个模板串,然后每个串除了字母,还有?或者*,?可以代替任何非空单个字符,*可以替代任何长度任何串,包括空字符串 ...

随机推荐

  1. seajs 2.3.0 加入jquery

    [前言] 上篇文章简单的介绍了seajs的使用,下午使用seajs整合jquery就碰到问题了. 下载seajs上的examples,里面直接require('jquery')没有不论什么问题, 我照 ...

  2. HomeSnap

    http://arnauddegiuli.github.io/HomeSnap/ OnBufferingUpdateListener https://github.com/LuckyJayce/Mat ...

  3. MySQL Troubleshoting:Waiting on query cache mutex 腾讯数据库工程师:幕南风

    http://blog.itpub.net/26515977/viewspace-1208188/           今天被MySQL Query Cache 炕了.线上大量 Waiting on ...

  4. Python学习 之 函数

    1.为什么要使用函数 (1)降低编程难度:将复杂的问题分解成简单的小问题 (2)代码重用 2.函数的定义 def 函数名(参数列表):#可以没有参数 函数体 3.函数缺省参数(默认参数):设置默认参数 ...

  5. Linux环境变量的修改(永久,暂时)

    Linux修改环境变量,很简单但很重要 一.Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1. 永久的:需要修改配置文件,变量永久生效. 2. 临时的:使用export命令 ...

  6. BFS-hdu-1226-超级密码

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1226 题目意思: 给一个N,给nn个jj进制的数字,问最小的不超过500位的由这些数字组成的jj进制 ...

  7. 详解ARM的AMBA设备中的 DMA设备PL08X的Linux驱动

    1. 此文目的记录笔者对ARM的PL08x的DMA驱动PL08x.c理解.给其他不熟悉此DMA驱动的读者一点借鉴和参考.2. 适合读者你已经具备一定驱动编程能力,知道一些最基本的概念,比如用于输出输出 ...

  8. 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 ...

  9. cocos2d-x使用ant打包

    1. 下载apache-ant-1.9.3,然后添加环境变量ANT_HOME = D:\dev_envir\apache-ant-1.9.3(你自己的ant根目录),再在path中添加路径:%ANT_ ...

  10. PHP读书笔记(3)-常量

    什么是常量 什么是常量?常量可以理解为值不变的量 :或者是常量值被定义后,在脚本的其他任何地方都不可以被改变.手册上是这么定义PHP的常量:常量是一个简单值的标识符(名字).如同其名称所暗示的,在脚本 ...