字典树模板( 指针版 && 数组版 )
模板 :
#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 ...
随机推荐
- 【HANA系列】SAP HANA SQL获取当前日期最后一天
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL获取当前 ...
- PSP周总结03
周日 周一 周二 周三 周四 周五 周六 所花时间 120 150 190 180 180 300 代码量 159 372 博客量 1 了解的知识点 阅读构建之法 软件工程概论 阅读构建之法 图书 ...
- Hand on Machine Learning第三章课后作业(2):其余小练习
-#!/usr/bin/env python -# # # -- coding: utf-8 -- -# # # @Time : 2019.5.22 14:09 -# # # @Author : An ...
- Ansible-playbook服务器初始化
一.什么是Playbook playbook可以理解为ansible的shell脚本,它是一个编排工具,作用是使用编排出能够重复利用的ansible脚本,并并发处理多台服务器. 二.playbook使 ...
- kafka消费者脚本无法启动问题
console-consumer can't rebalance after 4 retries 解决方案:kafka0.9版本换成1.0版本 究竟是怎么回事我也不知道
- Simplify Path(路径简化)
问题: 来源:https://leetcode.com/problems/simplify-path Given an absolute path for a file (Unix-style), s ...
- nodejs遍历文件夹下并操作HTML/CSS/JS/PNG/JPG
需求描述,由于工作的需要,需要将原本用于1280 720的网页改为1920 1080的网页(电视端页面).需求可以拆分为两部分,代码部分的修改以及图片的修改.在代码部分,需要将所有位置以及大小相关的值 ...
- go & flag
参考 Golang下的flag模块使用 Go基础篇[第6篇]: 内置库模块 flag
- 在django中使用循环与条件语言
{% if not Article_type_id %} <li class="active"><a href="/">全部</a ...
- 毛玻璃效果 css
毛玻璃效果 <style> .container{ width: 287px; height: 285px; background-image: url(img/background.pn ...