hiho一下 第二周&第四周:从Trie树到Trie图
hihocoder #1014 题目地址:http://hihocoder.com/problemset/problem/1014
hihocoder #1036 题目地址: http://hihocoder.com/problemset/problem/1036
trie图其实就是trie树+KMP
#1014trie树
- #include<stdio.h>
- #include <algorithm>
- #include <cstring>
- #include <string.h>
- #include <iostream>
- #include <list>
- #include <map>
- #include <set>
- #include <stack>
- #include <string>
- #include <utility>
- #include <vector>
- #include <cstdio>
- #include <cmath>
- using namespace std;
- typedef struct Trie_node
- {
- int count; // 统计单词前缀出现的次数
- struct Trie_node* next[]; // 指向各个子树的指针
- bool exist; // 标记该结点处是否构成单词
- }TrieNode , *Trie;
- Trie createTrieNode()
- {
- TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode));
- node->count = ;
- node->exist = false;
- memset(node->next , , sizeof(node->next)); // 初始化为空指针
- return node;
- }
- void Trie_insert(Trie root, char* word)
- {
- Trie node = root;
- char *p = word;
- int id;
- while( *p )
- {
- id = *p - 'a';
- if(node->next[id] == NULL)
- {
- node->next[id] = createTrieNode();
- }
- node = node->next[id];
- ++p;
- node->count += ; // 包括统计每个单词出现的次数
- }
- node->exist = true; // 可以构成一个单词
- }
- int Trie_search(Trie root, char* word)
- {
- Trie node = root;
- char *p = word;
- int id;
- while( *p )
- {
- id = *p - 'a';
- node = node->next[id];
- ++p;
- if(node == NULL)
- return ;
- }
- return node->count;
- }
- int main()
- {
- Trie root = createTrieNode(); // 字典树的根节点
- char str[] ;
- bool flag = false;
- int n ,m ;
- scanf ("%d", &n);
- for( int i = ; i < n ; i++)
- {
- scanf ("%s", str);
- Trie_insert(root , str);
- }
- scanf ("%d", &m);
- for( int i = ; i < m ; i++)
- {
- scanf ("%s", str);
- printf("%d\n",Trie_search(root , str));
- }
- return ;
- }
#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指针跳转到具有最长公共前后缀的字符继续匹配。
- #include<stdio.h>
- #include <algorithm>
- #include <cstring>
- #include <string.h>
- #include <iostream>
- #include <list>
- #include <map>
- #include <set>
- #include <stack>
- #include <string>
- #include <utility>
- #include <queue>
- #include <vector>
- #include <cstdio>
- #include <cmath>
- using namespace std;
- typedef struct Trie_node
- {
- int count; // 统计单词前缀出现的次数
- struct Trie_node* next[];
- bool exist; // 标记该结点处是否构成单词
- struct Trie_node* prev; //前缀节点
- }TrieNode , *Trie;
- Trie createTrieNode()
- {
- TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode));
- node->prev=NULL;
- node->count = ;
- node->exist = false;
- memset(node->next , , sizeof(node->next));
- return node;
- }
- void Trie_insert(Trie root, char* word)
- {
- Trie node = root;
- char *p = word;
- int id;
- while( *p )
- {
- id = *p - 'a';
- if(node->next[id] == NULL)
- {
- node->next[id] = createTrieNode();
- }
- node = node->next[id];
- ++p;
- node->count += ; // 统计每个单词出现的次数
- }
- node->exist = true; // 单词结束的地方标记
- }
- void Trie_build(Trie root) //Trie树和Tie图的区别就在于此,类似于KMP构造失配函数的一个过程
- {
- queue<Trie> Q; //利用bfs构造prev指针,队列实现BFS
- Trie node=root;
- for(int i=;i<;i++)//根节点的子节点的rev都是根节点,根节点的prev也是根节点
- {
- if(node->next[i]!=NULL)
- {
- node->next[i]->prev=root;
- Q.push(node->next[i]);
- }
- }
- while(!Q.empty())
- {
- node=Q.front();
- Q.pop();
- for(int i=; i<; i++)
- {
- Trie p=node->next[i];
- if(p!=NULL&&p->exist==false) //若此处能构成单词则不用处理prev
- {
- Trie prev=node->prev; //上一个结点的前缀节点
- while(prev)
- {
- if(prev->next[i]!=NULL)
- {
- p->prev=prev->next[i]; //prev指向与字符p相同的结点
- if(p->prev->exist==true)
- p->exist=true;
- break;
- }
- else
- prev=prev->prev;
- }
- if(p->prev==NULL)//如果没有与p前缀相同的节点,则指向root
- p->prev=root;
- Q.push(p);
- }
- }
- }
- }
- bool Trie_search(Trie root, char* word)
- {
- Trie node = root;
- char *p = word;
- int id;
- while( *p )
- {
- id = *p - 'a';
- while(true)
- {
- if(node->next[id]!=NULL) //匹配成功
- {
- node = node->next[id];
- if(node->exist)
- return true;
- break;
- }
- else node=node->prev; //类似KMP的失配过程,在当前字符匹配失败时,跳转到具有最长公共前后缀的字符继续匹配
- if(node==root||node==NULL){
- node=root;
- break;
- }
- }
- p++;
- }
- return false;
- }
- char str[] ;
- int main()
- {
- Trie root = createTrieNode(); // 初始化字典树的根节点
- bool flag = false;
- int n ;
- scanf ("%d", &n);
- for( int i = ; i < n ; i++)
- {
- scanf ("%s", str);
- Trie_insert(root , str);
- }
- Trie_build(root);
- scanf ("%s", str);
- if(Trie_search(root , str)) printf("YES\n");
- else printf("NO\n");
- return ;
- }
hiho一下 第二周&第四周:从Trie树到Trie图的更多相关文章
- 笔试算法题(39):Trie树(Trie Tree or Prefix Tree)
议题:TRIE树 (Trie Tree or Prefix Tree): 分析: 又称字典树或者前缀树,一种用于快速检索的多叉树结构:英文字母的Trie树为26叉树,数字的Trie树为10叉树:All ...
- hiho一下 第二周 trie树
Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路 ...
- 编程之美--2. Trie树 (Trie图)
#1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助, ...
- 双数组Trie树 (Double-array Trie) 及其应用
双数组Trie树(Double-array Trie, DAT)是由三个日本人提出的一种Trie树的高效实现 [1],兼顾了查询效率与空间存储.Ansj便是用DAT(虽然作者宣称是三数组Trie树,但 ...
- hihoCoder 1014 Trie树 (Trie)
#1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho是一对好朋友.出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮 ...
- hiho一下第二周 Trie树
题目链接:http://hihocoder.com/problemset/problem/1014 #include <iostream> #include <cstdio> ...
- hihoCoder hiho一下 第二周 #1014 : Trie树(Trie树基本应用)
思路: 完全看题目中的介绍就行了.还有里面的input写道:不保证是英文单词,也有可能是火星文单词哦.比赛结束后的提交是不用考虑26个字母之外的,都会AC,如果考虑128种可能的话,爆了内存.步骤就是 ...
- 【hiho一下第二周 】Trie树
[题目链接]:http://hihocoder.com/problemset/problem/1014 [题意] [题解] 在字典树的域里面加一个信息cnt; 表示这个节点下面,记录有多少个单词; 在 ...
- hihocoder_1014: Trie树(Trie树模板题)
题目链接 #include<bits/stdc++.h> using namespace std; ; struct T { int num; T* next[]; T() { num=; ...
随机推荐
- 阅读 Android源码的一些姿势
日常开发中怎么阅读源码 找到正确的源码 IDE 是日常经常用的东西,Eclipse 就不说了,直接从 Android Studio(基于 IntelliJ Community 版本改造)开始. 我们平 ...
- 设计模式之中介者模式(php实现)
github地址:https://github.com/ZQCard/design_pattern /** * 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性. ...
- httpd配置文件中重写函数Rewrite
[RewriteCond%{HTTP_HOST}^(www\.)?xxx\.com$] 这是重写条件,前面%{HTTP_HOST}表示当前访问的网址,只是指前缀部分,格式是www.xxx.com不包括 ...
- Section Formula
https://brilliant.org/wiki/section-formula/
- iptables 的学习资源
慕课网:https://www.imooc.com/video/7617 马哥linux视频:http://edu.51cto.com//center/course/lesson/index?id=9 ...
- [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 ...
- 11. 配置ContextPath【从零开始学Spring Boot】
转载:http://blog.csdn.net/linxingliang/article/details/51637036 spring boot默认是/ ,这样直接通过http://ip:port/ ...
- Linux 常见安全检查方法
Linux 常见安全检查方法进行概要说明: 一.检查系统密码文件,查看文件修改日期 # ls -l /etc/passwd 二.查看 passwd 文件中有哪些特权用户 # awk -F: '$3= ...
- 迭代器适配器(一)back_inserter和front_inserter的实现
本文讨论back_inserter和front_inserter的实现. 当我们调用copy函数的时候,要确保目标容器具有足够大的空间,例如: //将other的所有元素拷贝到以coll.begin( ...
- UltraISO 9.6.5.3237
注册信息: 用户名:Guanjiu 注册码:A06C-83A7-701D-6CFC