hihocoder #1014 题目地址:http://hihocoder.com/problemset/problem/1014

hihocoder #1036 题目地址: http://hihocoder.com/problemset/problem/1036

trie图其实就是trie树+KMP

#1014trie树

  1. #include<stdio.h>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <string.h>
  5. #include <iostream>
  6. #include <list>
  7. #include <map>
  8. #include <set>
  9. #include <stack>
  10. #include <string>
  11. #include <utility>
  12. #include <vector>
  13. #include <cstdio>
  14. #include <cmath>
  15.  
  16. using namespace std;
  17.  
  18. typedef struct Trie_node
  19. {
  20. int count; // 统计单词前缀出现的次数
  21. struct Trie_node* next[]; // 指向各个子树的指针
  22. bool exist; // 标记该结点处是否构成单词
  23. }TrieNode , *Trie;
  24.  
  25. Trie createTrieNode()
  26. {
  27. TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode));
  28. node->count = ;
  29. node->exist = false;
  30. memset(node->next , , sizeof(node->next)); // 初始化为空指针
  31. return node;
  32. }
  33.  
  34. void Trie_insert(Trie root, char* word)
  35. {
  36. Trie node = root;
  37. char *p = word;
  38. int id;
  39. while( *p )
  40. {
  41. id = *p - 'a';
  42. if(node->next[id] == NULL)
  43. {
  44. node->next[id] = createTrieNode();
  45. }
  46. node = node->next[id];
  47. ++p;
  48. node->count += ; // 包括统计每个单词出现的次数
  49. }
  50. node->exist = true; // 可以构成一个单词
  51. }
  52.  
  53. int Trie_search(Trie root, char* word)
  54. {
  55. Trie node = root;
  56. char *p = word;
  57. int id;
  58. while( *p )
  59. {
  60. id = *p - 'a';
  61. node = node->next[id];
  62. ++p;
  63. if(node == NULL)
  64. return ;
  65. }
  66. return node->count;
  67. }
  68.  
  69. int main()
  70. {
  71. Trie root = createTrieNode(); // 字典树的根节点
  72. char str[] ;
  73. bool flag = false;
  74. int n ,m ;
  75. scanf ("%d", &n);
  76. for( int i = ; i < n ; i++)
  77. {
  78. scanf ("%s", str);
  79. Trie_insert(root , str);
  80. }
  81. scanf ("%d", &m);
  82. for( int i = ; i < m ; i++)
  83. {
  84. scanf ("%s", str);
  85. printf("%d\n",Trie_search(root , str));
  86. }
  87. return ;
  88. }

#1036trie图

其实就是trie树+KMP

数据结构与trie树一样,加了一个prev指针,作用类似于KMP的失配函数next[]

Trie_insert函数不变

添加一个构造prev的函数Trie_build()。

prev指针的作用:在匹配失败时跳转到具有公共前缀的字符继续匹配,类似于KMP的失配函数next[]。

利用bfs构造prev指针。

指针prev指向与字符p相同的结点,如果没有与p前缀相同的节点,则指向root

根节点的前缀是根节点

最后字符匹配的Trie_search()函数类似于KMP的过程,在当前字符匹配失败时,利用prev指针跳转到具有最长公共前后缀的字符继续匹配。

  1. #include<stdio.h>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <string.h>
  5. #include <iostream>
  6. #include <list>
  7. #include <map>
  8. #include <set>
  9. #include <stack>
  10. #include <string>
  11. #include <utility>
  12. #include <queue>
  13. #include <vector>
  14. #include <cstdio>
  15. #include <cmath>
  16.  
  17. using namespace std;
  18.  
  19. typedef struct Trie_node
  20. {
  21. int count; // 统计单词前缀出现的次数
  22. struct Trie_node* next[];
  23. bool exist; // 标记该结点处是否构成单词
  24. struct Trie_node* prev; //前缀节点
  25. }TrieNode , *Trie;
  26.  
  27. Trie createTrieNode()
  28. {
  29. TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode));
  30. node->prev=NULL;
  31. node->count = ;
  32. node->exist = false;
  33. memset(node->next , , sizeof(node->next));
  34. return node;
  35. }
  36.  
  37. void Trie_insert(Trie root, char* word)
  38. {
  39. Trie node = root;
  40. char *p = word;
  41. int id;
  42. while( *p )
  43. {
  44. id = *p - 'a';
  45. if(node->next[id] == NULL)
  46. {
  47. node->next[id] = createTrieNode();
  48. }
  49. node = node->next[id];
  50. ++p;
  51. node->count += ; // 统计每个单词出现的次数
  52. }
  53. node->exist = true; // 单词结束的地方标记
  54. }
  55.  
  56. void Trie_build(Trie root) //Trie树和Tie图的区别就在于此,类似于KMP构造失配函数的一个过程
  57. {
  58. queue<Trie> Q; //利用bfs构造prev指针,队列实现BFS
  59. Trie node=root;
  60. for(int i=;i<;i++)//根节点的子节点的rev都是根节点,根节点的prev也是根节点
  61. {
  62. if(node->next[i]!=NULL)
  63. {
  64. node->next[i]->prev=root;
  65. Q.push(node->next[i]);
  66. }
  67. }
  68. while(!Q.empty())
  69. {
  70. node=Q.front();
  71. Q.pop();
  72. for(int i=; i<; i++)
  73. {
  74. Trie p=node->next[i];
  75. if(p!=NULL&&p->exist==false) //若此处能构成单词则不用处理prev
  76. {
  77. Trie prev=node->prev; //上一个结点的前缀节点
  78. while(prev)
  79. {
  80. if(prev->next[i]!=NULL)
  81. {
  82. p->prev=prev->next[i]; //prev指向与字符p相同的结点
  83. if(p->prev->exist==true)
  84. p->exist=true;
  85. break;
  86. }
  87. else
  88. prev=prev->prev;
  89. }
  90.  
  91. if(p->prev==NULL)//如果没有与p前缀相同的节点,则指向root
  92. p->prev=root;
  93. Q.push(p);
  94. }
  95. }
  96. }
  97. }
  98.  
  99. bool Trie_search(Trie root, char* word)
  100. {
  101. Trie node = root;
  102. char *p = word;
  103. int id;
  104. while( *p )
  105. {
  106. id = *p - 'a';
  107. while(true)
  108. {
  109. if(node->next[id]!=NULL) //匹配成功
  110. {
  111. node = node->next[id];
  112. if(node->exist)
  113. return true;
  114. break;
  115. }
  116. else node=node->prev; //类似KMP的失配过程,在当前字符匹配失败时,跳转到具有最长公共前后缀的字符继续匹配
  117. if(node==root||node==NULL){
  118. node=root;
  119. break;
  120. }
  121. }
  122. p++;
  123. }
  124. return false;
  125. }
  126.  
  127. char str[] ;
  128. int main()
  129. {
  130. Trie root = createTrieNode(); // 初始化字典树的根节点
  131. bool flag = false;
  132. int n ;
  133. scanf ("%d", &n);
  134. for( int i = ; i < n ; i++)
  135. {
  136. scanf ("%s", str);
  137. Trie_insert(root , str);
  138. }
  139. Trie_build(root);
  140. scanf ("%s", str);
  141. if(Trie_search(root , str)) printf("YES\n");
  142. else printf("NO\n");
  143. return ;
  144. }

hiho一下 第二周&第四周:从Trie树到Trie图的更多相关文章

  1. 笔试算法题(39):Trie树(Trie Tree or Prefix Tree)

    议题:TRIE树 (Trie Tree or Prefix Tree): 分析: 又称字典树或者前缀树,一种用于快速检索的多叉树结构:英文字母的Trie树为26叉树,数字的Trie树为10叉树:All ...

  2. hiho一下 第二周 trie树

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

  3. 编程之美--2. Trie树 (Trie图)

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

  4. 双数组Trie树 (Double-array Trie) 及其应用

    双数组Trie树(Double-array Trie, DAT)是由三个日本人提出的一种Trie树的高效实现 [1],兼顾了查询效率与空间存储.Ansj便是用DAT(虽然作者宣称是三数组Trie树,但 ...

  5. hihoCoder 1014 Trie树 (Trie)

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

  6. hiho一下第二周 Trie树

    题目链接:http://hihocoder.com/problemset/problem/1014 #include <iostream> #include <cstdio> ...

  7. hihoCoder hiho一下 第二周 #1014 : Trie树(Trie树基本应用)

    思路: 完全看题目中的介绍就行了.还有里面的input写道:不保证是英文单词,也有可能是火星文单词哦.比赛结束后的提交是不用考虑26个字母之外的,都会AC,如果考虑128种可能的话,爆了内存.步骤就是 ...

  8. 【hiho一下第二周 】Trie树

    [题目链接]:http://hihocoder.com/problemset/problem/1014 [题意] [题解] 在字典树的域里面加一个信息cnt; 表示这个节点下面,记录有多少个单词; 在 ...

  9. hihocoder_1014: Trie树(Trie树模板题)

    题目链接 #include<bits/stdc++.h> using namespace std; ; struct T { int num; T* next[]; T() { num=; ...

随机推荐

  1. 阅读 Android源码的一些姿势

    日常开发中怎么阅读源码 找到正确的源码 IDE 是日常经常用的东西,Eclipse 就不说了,直接从 Android Studio(基于 IntelliJ Community 版本改造)开始. 我们平 ...

  2. 设计模式之中介者模式(php实现)

    github地址:https://github.com/ZQCard/design_pattern /** * 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性. ...

  3. httpd配置文件中重写函数Rewrite

    [RewriteCond%{HTTP_HOST}^(www\.)?xxx\.com$] 这是重写条件,前面%{HTTP_HOST}表示当前访问的网址,只是指前缀部分,格式是www.xxx.com不包括 ...

  4. Section Formula

    https://brilliant.org/wiki/section-formula/

  5. iptables 的学习资源

    慕课网:https://www.imooc.com/video/7617 马哥linux视频:http://edu.51cto.com//center/course/lesson/index?id=9 ...

  6. [Algorithms] Classify Mystery Items with the K-Nearest Neighbors Algorithm in JavaScript

    The k-nearest neighbors algorithm is used for classification of unknown items and involves calculati ...

  7. 11. 配置ContextPath【从零开始学Spring Boot】

    转载:http://blog.csdn.net/linxingliang/article/details/51637036 spring boot默认是/ ,这样直接通过http://ip:port/ ...

  8. Linux 常见安全检查方法

    Linux 常见安全检查方法进行概要说明: 一.检查系统密码文件,查看文件修改日期 # ls -l /etc/passwd 二.查看 passwd 文件中有哪些特权用户 # awk -F: '$3= ...

  9. 迭代器适配器(一)back_inserter和front_inserter的实现

    本文讨论back_inserter和front_inserter的实现. 当我们调用copy函数的时候,要确保目标容器具有足够大的空间,例如: //将other的所有元素拷贝到以coll.begin( ...

  10. UltraISO 9.6.5.3237

    注册信息: 用户名:Guanjiu 注册码:A06C-83A7-701D-6CFC