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。

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

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

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

  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(0){
 16         memset(child,0,sizeof(child)); //初始化节点
 17     }
 18     
 19 };
 20 int RR[10200],CC[10200];
 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=0;i<Size;i++)
 35             root.child[i]=0;
 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]==0){
 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]==0){
 92                 
 93                 RR[cur->id]=r;
 94                 CC[cur->id]=c;
 95             }
 96         }
 97         
 98     }
 99     
100     
101     
102     //重载c风格
103     void find(const char *str,int r,int c){
104         
105         find(str,str+strlen(str),r,c);
106     }
107     
108     
109     
110     
111     
112 private:
113     
114     
115     //清空
116     void clear_node(node_type cur){
117         for(int i=0;i<Size;i++){
118             if(cur.child[i]==0)continue; //不存在
119             clear_node(*cur.child[i]);
120             delete cur.childe[i];
121             cur.child[i]=0;
122             if(--cur.node==0) break; //没有节点了
123             
124         }
125         
126     }
127     
128     
129     //
130     node_type root;
131     //字符转索引,类似hash
132     Index index;
133     
134 };
135 
136 class IndexClass{
137 public:
138     int operator[](const char key){
139         return key%26; //一个映射
140         
141     }
142     
143 };
144 char cc[501][501];
145 char s[21];
146 int mini(int a,int b){
147     return a>b?b:a;
148 }
149 int main(){
150     trie<26,IndexClass> t;
151     int R,C,i,j,l,ed;
152     scanf("%d%d",&R,&C);
153     getchar(); //读掉回车
154     for( i=0;i<R;i++)
155     {
156         
157         gets(cc[i]);
158     }
159         
160     int N=0;
161     while(gets(s)&&s[0]!='-'){
162         if(s[0]){
163             t.insert(s,N);   //用每一个要查找的单词构树
164                 N++;
165         }
166             
167     }
168     
169         for(i=0;i<R;i++)
170             for( j=0;j<C;j++){
171                 //向下
172                 memset(s,0,sizeof(s));
173                 if(i+20<R) ed=20;
174                 else ed=R-i;
175                 for(l=0;l<ed;l++){
176                     s[l]=cc[i+l][j];
177                     
178                 }
179             
180                 t.find(s,i+1,j+1);
181                 //向右
182                 memset(s,0,sizeof(s));
183                 if(j+20<C) ed=20;
184                 else ed=C-j;
185                 for( l=0;l<ed;l++){
186                     s[l]=cc[i][j+l];
187                     
188                 }
189                 
190                 t.find(s,i+1,j+1);
191 
192                 //右下
193                 memset(s,0,sizeof(s));
194                 if(i+20<R&&j+20<C) ed=20;
195                 else ed=mini(C-j,R-i);
196                 for( l=0;l<ed;l++){
197                     s[l]=cc[i+l][j+l];
198                     
199                 }
200             
201                 t.find(s,i+1,j+1);
202                 
203             }
204             
205             for( i=0;i<N;i++){
206                 
207                 if(RR[i]!=0||CC[i]!=0)
208                     printf("%d %d\n",RR[i]-1,CC[i]-1);
209                 else puts("-1 -1");
210             }
211             
212                         
213             
214             return 0;
215                         
216 }
View Code

 

 

posted @ 2014-04-22 10:26  dengyaolong  阅读(460)  评论(0编辑  收藏  举报