字典树模板( 指针版 && 数组版 )
模板 :
#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<algorithm>
using namespace std;
;
struct Trie
{
Trie *Next[maxn];
int v;
inline void init(){
;
; i<maxn; i++)
this->Next[i] = NULL;
}
};
Trie *root = (Trie *)malloc(sizeof(Trie));
void CreateTrie(char *str)
{
int len = strlen(str);
Trie *p = root, *tmp;
; i<len; i++){
int idx = str[i]-'a';
if(p->Next[idx] == NULL){
tmp = (Trie *)malloc(sizeof(Trie));
tmp->init();
p->Next[idx] = tmp;
}else p->Next[idx]->v++;
p = p->Next[idx];
}
p->v = -;//若为结尾,则将v改成-1,当然字典树里面的变量都是要依据题目
//设置并且在特定位置赋值的
}
int FindTrie(char *str)
{
int len = strlen(str);
Trie *p = root;
; i<len; i++){
int idx = str[i]-'a';
p = p->Next[idx];
//...进行一系列操作
}
}
inline void DelTrie(Trie *T)
{
if(T == NULL) return ;
; i<maxn; i++){
if(T->Next[i] != NULL)
DelTrie(T->Next[i]);
}
free(T);
return ;
}
int main(void)
{
root.init();//!!!
//...
}
指针版
#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<algorithm>
using namespace std;
+ ;
struct Trie
{
int Next[maxn], v;
inline void init(){
v = ;
memset(Next, -, sizeof(Next));
}
};
]; // 字典树可能最多的节点数,注意开足了!
;
void CreateTrie(char *str)
{
int len = strlen(str);
;
; i<len; i++){
int idx = str[i]-'a';
int nxt = Node[now].Next[idx];
){
nxt = ++tot;
Node[nxt].init();
Node[now].Next[idx] = nxt;
}else Node[nxt].v++;
now = nxt;
}
// Node[now].v = //尾部标志
}
int FindTrie(char *str)
{
int len = strlen(str);
;
int nxt;
; i<len; i++){
int idx = str[i]-'a';
) now = Node[now].Next[idx];
;
}
return Node[now].v;//返回该返回的值
}
数组版
字典树算法参考 ==> http://www.cnblogs.com/tanky_woo/archive/2010/09/24/1833717.html
IOI论文《浅析字母树在信息学竞赛中的应用》 ==> http://www.doc88.com/p-434727490439.html
相关题目 :
① HUD 1251
题意 : 给出很多单词(只有小写字母组成,不会有重复的单词出现),要求统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
分析 : 模板题,直接累加前缀即可
///数组版
#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<algorithm>
using namespace std;
+ ;
struct Trie
{
int Next[maxn], v;
inline void init(){
v = ;
memset(Next, -, sizeof(Next));
}
};
]; // 字典树可能最多的节点数,注意开足了!
;
void CreateTrie(char *str)
{
int len = strlen(str);
;
; i<len; i++){
int idx = str[i]-'a';
int nxt = Node[now].Next[idx];
){
nxt = ++tot;
Node[nxt].init();
Node[now].Next[idx] = nxt;
}else Node[nxt].v++;
now = nxt;
}
}
int FindTrie(char *str)
{
int len = strlen(str);
;
int nxt;
; i<len; i++){
int idx = str[i]-'a';
) now = Node[now].Next[idx];
;
}
return Node[now].v;
}
];
int main(void)
{
Node[].init();
while(gets(s)){
] == '\0') break;
CreateTrie(s);
}
while(scanf("%s", s)!=EOF){
printf("%d\n",FindTrie(s));
}
;
}
///指针版
#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<algorithm>
using namespace std;
;
struct Trie
{
Trie *Next[maxn];
int v;
inline void init(){
;
; i<maxn; i++)
this->Next[i] = NULL;
}
};
Trie *root = (Trie *)malloc(sizeof(Trie));
inline void CreateTrie(char *str)
{
int len = strlen(str);
Trie *p = root, *tmp;
; i<len; i++){
int idx = str[i]-'a';
if(p->Next[idx] == NULL){
tmp = (Trie *)malloc(sizeof(Trie));
tmp->init();
p->Next[idx] = tmp;
}else p->Next[idx]->v++;
p = p->Next[idx];
}
//p->v = -1;
}
int FindTrie(char *str)
{
int len = strlen(str);
Trie *p = root;
; i<len; i++){
int idx = str[i]-'a';
if(p->Next[idx] != NULL) p = p->Next[idx];
;
}
return p->v;
}
inline void DelTrie(Trie *T)
{
if(T == NULL) return ;
; i<maxn; i++){
if(T->Next[i] != NULL)
DelTrie(T->Next[i]);
}
free(T);
return ;
}
];
int main(void)
{
root->init();
while(gets(s)){
] == '\0') break;
CreateTrie(s);
}
while(scanf("%s", s)!=EOF){
printf("%d\n",FindTrie(s));
}DelTrie(root);
;
}
② HDU 2846
题意 : 给出 P 个单词和 Q 个询问,对于每一次询问给出询问串是多少个 P 中字符的子串
分析 : 利用KMP的话可以做,但是复杂度爆炸,可以利用字典树,将 P 个单词的每一个以及其子串全部丢去建树,最后问询串直接去跑字典树查询即可。但是在字典树上权值的累加需要注意,例如 abb 这个串,在分解的时候 b 即属于 bb 也属于 b 那么当问询 b 这个字符串的时候就应该输出 2 吗?很显然不是,对于当前分解的串,我们需要给它加一个 id 来判断当前的字符是否是由同一个串分解而来的,就能避免重复计算。
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<malloc.h>
using namespace std;
;
struct Trie{ Trie *Next[maxn]; int v, who; };
Trie *root = (Trie *)malloc(sizeof(Trie));
void CreateTrie(char *str, int who)
{
int len = strlen(str);
root->who = who;
; st<=len-; st++){
Trie *p = root, *tmp;
for(int i=st; i<len; i++){
int id = str[i] - 'a';
if(p->Next[id]==NULL){
tmp = (Trie *)malloc(sizeof(Trie));
tmp->v = ;
tmp->who = who;
; j<maxn; j++)
tmp->Next[j] = NULL;
p->Next[id] = tmp;
p = p->Next[id];
}else{
if(who != p->Next[id]->who) {
p->Next[id]->v++;
p->Next[id]->who = who;
}
p = p->Next[id];
}
}
}
}
;
bool TrieFind(int n, char *str) //代码将演示在树上找str的前缀是否存在
{
ans = ;
int len = strlen(str);
Trie *p = root;
; i<len; i++){
int id = str[i] - 'a';
if(p->Next[id] != NULL) p = p->Next[id];
else return false;
}
ans = p->v;
return true;
}
inline void DelTrie(Trie *T)
{
int i;
if(T == NULL) return ;
; i<maxn; i++){
if(T->Next[i] != NULL){
DelTrie(T->Next[i]);
}
}
free(T);
return ;
}
];
int main(void)
{
; i<maxn; i++) root->Next[i] = NULL;
root->who = -;
root->v = ;
int n, q;
scanf("%d", &n);
; i<n; i++){
scanf("%s", str);
CreateTrie(str, i);
}
scanf("%d", &q);
; i<q; i++){
scanf("%s", str);
if(TrieFind(n, str)) printf("%d\n", ans);
");
}
DelTrie(root);
;
}
字典树模板( 指针版 && 数组版 )的更多相关文章
- 字典树模板 HDU - 1251
题意: 给一些单词,换行键后,查找以后输入的单词作为前缀的话们在之前出现过几次. 思路: 字典树模板----像查字典的顺序一样 #include<string> #include<s ...
- hdu1521(字典树模板)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1251 题意: 中文题诶~ 思路: 字典树模板 代码1: 动态内存, 比较好理解一点, 不过速度略慢, ...
- 【统计难题】【HDU - 1251】【map打表或字典树】【字典树模板】
思路 题意:题目为中文题,这里不再过多阐述. 思路1:可以在读入单词表的过程中将单词分解,用map将它一 一记录 思路2:利用字典树,这个方法较快些,下面代码中会分别给出数组和结构体指针两种形式的字典 ...
- HDU - 1251 字典树模板题
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input输入数据的第一部 ...
- 字典树模板题(统计难题 HDU - 1251)
https://vjudge.net/problem/HDU-1251 标准的字典树模板题: 也注意一下输入方法: #include<iostream> #include<cstdi ...
- CH 1601 - 前缀统计 - [字典树模板题]
题目链接:传送门 描述给定 $N$ 个字符串 $S_1,S_2,\cdots,S_N$,接下来进行 $M$ 次询问,每次询问给定一个字符串 $T$,求 $S_1 \sim S_N$ 中有多少个字符串是 ...
- HDU:1251-统计难题(字典树模板,动态建树,静态建树)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1251 统计难题 Time Limit: 4000/2000 MS (Java/Others) Memor ...
- P1184 高手之在一起(字典树模板题,hash算法, map)
哎,唯一值得说明的是,这道题的输入有bug 先把字典树的算法模板放一下 #include<iostream> #include<cstring> using namespace ...
- hdu 1671 Phone List 字典树模板
Given a list of phone numbers, determine if it is consistent in the sense that no number is the pref ...
随机推荐
- python3 基本数据类型_1
不得已,要学习python3了,之前了解到py2与py3有很大不同,不过学起来才能感觉到,比如print. 不过,同样的代码,可以使用py3,py2执行,结果也相似,大家可以看看. 大概因为初学,还未 ...
- 【HANA系列】SAP HANA SQL获取上周的周一
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL获取上周 ...
- 20191127 Spring Boot官方文档学习(4.14-4.17)
4.14.使用RestTemplate调用REST服务 如果需要从应用程序调用远程REST服务,则可以使用Spring Framework的RestTemplate类.由于RestTemplate实例 ...
- Zabbix-常见问题解决
1.创建图形后字符乱码 # cd /usr/share/zabbix/fonts将Windows里面的 windows 控制面板——>字体——>如选择 “黑体”——>上传到当前目录# ...
- [Python3] 042 日志
目录 LOG 1. 日志相关概念 1.1 日志的级别 level 1.2 LOG 的作用 1.3 日志信息 1.4 成熟的第三方日志 1.5 注意 2. Logging 模块 2.1 日志级别 2.2 ...
- java锁的使用
1 synchronize和ReentrantLock synchronize锁是jvm内置的锁,它锁的是synchronize所在的类的对象,要同步那么就只能有一个对象. ReentrantLock ...
- 小白学Python——用 百度AI 实现 OCR 文字识别
百度AI功能还是很强大的,百度AI开放平台真的是测试接口的天堂,免费接口很多,当然有量的限制,但个人使用是完全够用的,什么人脸识别.MQTT服务器.语音识别等等,应有尽有. 看看OCR识别免费的量 快 ...
- Scrapy 教程(十)-管道与数据库
Scrapy 框架将爬取的数据通过管道进行处理,即 pipelines.py 文件. 管道处理流程 一.定义 item item 表示的是数据结构,定义了数据包括哪些字段 class TianqiIt ...
- activemq热备与消息丢失
1. 解压 tar -zxvf apache-activemq-5.12.0-bin.tar.gz2. 改名 mv apache-activemq-5.12.0 activemq3. cd activ ...
- linux 建立 MySQL 账号
以 root 身份登录 Linux 系统,创建 mysql 组和用户 [root@Nagios-Server ~]# groupadd mysql [root@Nagios-Server ~]# us ...