字典树 ZOJ1109 HDU1251 PKU1204 HDU1075

5 篇文章 0 订阅
2 篇文章 0 订阅

又称单词查找树Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

假设有abc,abcd,abd, b, bcd,efg,hii这7个单词,可构建字典树如下:

 

查找一个字符串时,我们只需从根结点按字符串中字符出现顺序依次往下走。如果到最后字符串结束时,对应的结点标记为红色,则该字符串存在;否则不存在。
插入时也只需从根结点往下遍历,碰到已存在的字符结点就往下遍历,否则,建立新结点;最后标记最后一个字符的结点为红色即可。

性质 

  它有3个基本性质:

      根节点不包含字符,除根节点外每一个节点都只包含一个字符。

      从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

      每个节点的所有子节点包含的字符都不相同。

基本操作 

      其基本操作有:查找 插入和删除,当然删除操作比较少见.我在这里只是实现了对整个树的删除操作,至于单个word的删除操作也很简单.

搜索字典项目的方法为: 

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

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

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

  (4) 迭代过程……

  (5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。

  其他操作类似处理

以上内容来自百度百科。对应练习:ZOJ1109  HDU1251

ZOJ1109 Language of FatMouse

map方法 1320MS 9556K

复制代码
代码
复制代码
          
          
#include < iostream > #include < string > #include < map > #pragma warning (disable:4786) using namespace std; int main() { map < string , string > m; int len,i; char str[ 40 ],a[ 20 ],b[ 20 ]; while ( 1 ) { gets(str); len = strlen(str); if (len == 0 ) break ; for (i = 0 ;str[i] != ' ' ;i ++ ); strncpy(a,str,i); a[i] = 0 ; strncpy(b,str + i + 1 ,len - i - 1 ); b[len - i - 1 ] = 0 ; m[b] = a; } map < string , string > ::iterator it; while (scanf( " %s " ,str) != EOF) { it = m.find(str); if (it != m.end()) cout << ( * it).second << endl; else puts( " eh " ); } return 0 ; }
复制代码
复制代码

字典树:140MS 14960K

复制代码
代码
复制代码
          
          
#include < stdio.h > #include < stdlib.h > #include < string .h > #define N 100006 typedef struct node{ char s[ 12 ]; int h; struct node * next[ 26 ]; } * Tree,T; void init(Tree & root) { root = (Tree)malloc( sizeof (T)); root -> h = 0 ; for ( int i = 0 ;i < 26 ;i ++ ) root -> next[i] = NULL; } void insert( char path[], char s[],Tree root) { int len,i,j; len = strlen(path); for (i = 0 ;i < len;i ++ ) { if (root -> next[path[i] - ' a ' ] == NULL) { Tree t = (Tree)malloc( sizeof (T)); for (j = 0 ;j < 26 ;j ++ ) { t -> next[j] = NULL; t -> h = 0 ; } root -> next[path[i] - ' a ' ] = t; } root = root -> next[path[i] - ' a ' ]; } root -> h = 1 ; strcpy(root -> s,s); } void find( char s[],Tree root) { int len,i; len = strlen(s); for (i = 0 ;i < len;i ++ ) { if (root -> next[s[i] - ' a ' ] != NULL) root = root -> next[s[i] - ' a ' ]; else break ; } if (i == len && root -> h == 1 ) puts(root -> s); else puts( " eh " ); } int main() { Tree root; int len,i; char str[ 25 ],a[ 12 ],b[ 12 ]; init(root); while ( 1 ) { gets(str); len = strlen(str); if (len == 0 ) break ; for (i = 0 ;str[i] != ' ' ;i ++ ); strncpy(a,str,i); a[i] = 0 ; strncpy(b,str + i + 1 ,len - i - 1 ); b[len - i - 1 ] = 0 ; insert(b,a,root); } while (scanf( " %s " ,str) != EOF) find(str,root); return 0 ; }
复制代码
复制代码

 

HDU1251 统计难题  140MS 43736K

复制代码
代码
复制代码
          
          
#include < stdio.h > #include < stdlib.h > #include < string .h > typedef struct node{ int cnt; struct node * next[ 26 ]; } * Tree,T; Tree root; void insert( char * str) // 建字典树 { int i; Tree p,newnode; p = root; for (; * str;str ++ ) { if (p -> next[ * str - ' a ' ] != NULL) { p = p -> next[ * str - ' a ' ]; p -> cnt ++ ; } else { newnode = (Tree)malloc( sizeof (T)); for (i = 0 ;i < 26 ;i ++ ) newnode -> next[i] = NULL; p -> next[ * str - ' a ' ] = newnode; p = p -> next[ * str - ' a ' ]; p -> cnt = 1 ; } } } int find( char * str) // 查找 { Tree p; p = root; for (; * str;str ++ ) { if (p -> next[ * str - ' a ' ] != NULL) p = p -> next[ * str - ' a ' ]; else return 0 ; } return p -> cnt; } int main() { int i; char str[ 20 ]; root = (Tree)malloc( sizeof (T)); for (i = 0 ;i < 26 ;i ++ ) root -> next[i] = NULL; root -> cnt = 0 ; while (gets(str)) { if (strcmp(str, "" ) == 0 ) break ; insert(str); } while (gets(str)) printf( " %d\n " ,find(str)); return 0 ; }
复制代码
复制代码

 

PKU1204 Word Puzzles

字典树:1485MS 14320K(对给定的单词建树,对表进行暴力search)

复制代码
代码
复制代码
          
          
#include < stdio.h > #include < string .h > #include < stdlib.h > #define N 1002 typedef struct tree{ int count; struct tree * next[ 26 ]; } * Tree,T; Tree root; int l,c,w; char map[N][N]; int result[N][ 3 ]; int dir[ 8 ][ 2 ] = {{ - 1 , 0 },{ - 1 , 1 },{ 0 , 1 },{ 1 , 1 },{ 1 , 0 },{ 1 , - 1 },{ 0 , - 1 },{ - 1 , - 1 }}; void insert( char * s, int con) { Tree p = root,q; for ( int i = 0 ;s[i];i ++ ) { if (p -> next[s[i] - ' A ' ] == NULL) { q = (Tree)malloc( sizeof (T)); memset(q -> next, 0 , sizeof (q -> next)); q -> count =- 1 ; p -> next[s[i] - ' A ' ] = q; } p = p -> next[s[i] - ' A ' ]; } p -> count = con; } void search( int x, int y, int k) { int x1 = x,y1 = y; Tree p = root; while (x1 >= 0 && x1 < l && y1 >= 0 && y1 < c) { int id = map[x1][y1] - ' A ' ; if (p -> next[id] == NULL) break ; else p = p -> next[id]; if (p -> count !=- 1 ) { result[p -> count][ 0 ] = x; result[p -> count][ 1 ] = y; result[p -> count][ 2 ] = k + ' A ' ; } x1 += dir[k][ 0 ]; y1 += dir[k][ 1 ]; } } void slove() { int i,j,k; for (i = 0 ;i < l;i ++ ) for (j = 0 ;j < c;j ++ ) for (k = 0 ;k < 8 ;k ++ ) search(i,j,k); for (i = 0 ;i < w;i ++ ) printf( " %d %d %c\n " ,result[i][ 0 ],result[i][ 1 ],result[i][ 2 ]); } int main() { int i; char word[N]; scanf( " %d%d%d " , & l, & c, & w); getchar(); root = (Tree)malloc( sizeof (T)); memset(root -> next, 0 , sizeof (root -> next)); for (i = 0 ;i < l;i ++ ) gets(map[i]); for (i = 0 ;i < w;i ++ ) { gets(word); insert(word,i); } slove(); return 0 ; }
复制代码
复制代码

据说这题还可以用AC自动机实现,不了解AC自动机,有待提高……

 

HDU1075 同ZOJ1109同一道理,字典树基本应用。

map方法 3375MS 42368K 752B

复制代码
代码
复制代码
          
          
#include < iostream > #include < string > #include < map > using namespace std; int main() { map < string , string > M; string a,b; cin >> a; while (cin >> a,a != " END " ) { cin >> b; M[b] = a; } cin >> a; getchar(); char tmp[ 3005 ]; while (gets(tmp),strcmp(tmp, " END " )) { int len = strlen(tmp); tmp[len ++ ] = ' ' ; tmp[len] = 0 ; b = "" ; for ( int i = 0 ;i < len;i ++ ) { if ( ! islower(tmp[i])) { if (M[b] != "" ) cout << M[b]; else cout << b; b = "" ; if (i != len - 1 ) cout << tmp[i]; } else b += tmp[i]; } cout << endl; } return 0 ; }
复制代码
复制代码

 

字典树:437MS 59796K 1274B(可以用做模板了吧)

复制代码
代码
复制代码
          
          
#include < stdio.h > #include < string .h > #include < ctype.h > #include < stdlib.h > typedef struct node{ node * next[ 26 ]; int h; char word[ 12 ]; node() { h = 0 ; memset(next, 0 , sizeof (next)); } } * Tree,T; Tree root = new node(); void insert( char * eng, char * mar) { Tree p = root; while ( * mar) { int id =* mar - ' a ' ; if (p -> next[id] == NULL) p -> next[id] = new node(); p = p -> next[id]; mar ++ ; } p -> h = 1 ; strcpy(p -> word,eng); } char * find( char * str) { Tree p = root; while ( * str) { int id =* str - ' a ' ; if (p -> next[id] == NULL) break ; p = p -> next[id]; str ++ ; } if ( * str == NULL && p -> h == 1 ) return p -> word; else return NULL; } int main() { int i,k,len; char a[ 12 ],b[ 12 ],tmp[ 3005 ],tp[ 3005 ]; char * p; scanf( " %s " ,a); while (scanf( " %s " ,a) && strcmp(a, " END " ) != 0 ) { scanf( " %s " ,b); insert(a,b); } scanf( " %s " ,a); getchar(); k = 0 ; while (gets(tmp),strcmp(tmp, " END " )) { len = strlen(tmp); tmp[len ++ ] = ' ' ; tmp[len] = 0 ; for (i = 0 ;i < len;i ++ ) { if ( ! islower(tmp[i])) { tp[k] = 0 ; k = 0 ; p = find(tp); if (p) printf( " %s " ,p); else printf( " %s " ,tp); if (i != len - 1 ) putchar(tmp[i]); } else tp[k ++ ] = tmp[i]; } puts( "" ); } return 0 ; }
复制代码
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值