15
ACM 程程程程

ACM 程序设计

Embed Size (px)

DESCRIPTION

ACM 程序设计. 集训队讲座. 字典树 ( Trie ). 导引问题 ( HDOJ- 1251 ). Ignatius 最近遇到一个难题 , 老师交给他很多单词 ( 只有小写字母组成 , 不会有重复的单词出现 ), 现在老师要他统计出以某个字符串为前缀的单词数量 ( 单词本身也是自己的前缀 ). 初步分析 ( Brute-force ). 假设单词表容量为 M ,需要统计的前缀数量为 N ,单词的平均长度为 L ,则常规算法的时间复杂度是?. Question: 如果单词表容量很大 -> 查找效率 ? -> 低 更有效率的方法:字典树. 什么是字典树?. - PowerPoint PPT Presentation

Citation preview

Page 1: ACM 程序设计

ACM 程序设计

Page 2: ACM 程序设计

集训队讲座

字典树( Trie )

Page 3: ACM 程序设计

导引问题 (HDOJ-1251)

Ignatius 最近遇到一个难题 , 老师交给他很多单词 ( 只有小写字母组成 , 不会有重复的单词出现 ), 现在老师要他统计出以某个字符串为前缀的单词数量 ( 单词本身也是自己的前缀 ).

Page 4: ACM 程序设计

初步分析( Brute-force )

Question:如果单词表容量很大 -> 查找效率 ? -> 低更有效率的方法:字典树

假设单词表容量为 M ,需要统计的前缀数量为 N ,单词的平均长度为 L ,则常规算法的时间复杂度是?

Page 5: ACM 程序设计

什么是字典树?字典树:又称为 Trie ,是一种用于快速检索的多叉树结构。 Trie 把要查找的关键词看作一个字符序列,并根据构成关键词字符的先后顺序构造用于检索的树结构;一棵 m 度的 Trie 树或者为空,或者由 m 棵m 度的 Trie 树构成。特别地:和二叉查找树不同,在 Trie 树中,每个结点上并非存储一个元素。

Page 6: ACM 程序设计

Trie 的图示特点: 利用串的公共前

缀 -> 节约内存 根结点不包含任何

字母 其余结点仅包含一

个字母 ( 非元素 ) 每个结点的子节点

包含字母不同

Page 7: ACM 程序设计

Trie 的查找(最主要的操作)(1) 在 trie 树上进行检索总是始于根结点。(2) 取得要查找关键词的第一个字母,并根据该字

母选择对应的子树并转到该子树继续进行检索。 (3) 在 (5) 在某个结点处,关相应的子树上,取得要

查找关键词的第二个字母,并进一步选择对应的子树进行检索。

(4) ... 键词的所有字母已被取出,则读取附在该结点上的

信息,即完成查找。

Page 8: ACM 程序设计

Trie 的数据结构定义 struct dictree { dictree *child[26]; int n; // 根据需要变化 };

dictree *root;

Page 9: ACM 程序设计

查找效率分析 在 trie 树中查找一个关键字的时间和树中包含的

结点数无关,而取决于组成关键字的字符数。(对比:二叉查找树的查找时间和树中的结点数有关 O(log2

n) 。) 如果要查找的关键字可以分解成字符序列且不是

很长,利用 trie 树查找速度优于二叉查找树。 若关键字长度最大是 5 ,则利用 trie 树,利用 5

次比较可以从 265 = 11881376 个可能的关键字中检索出指定的关键字。而利用二叉查找树至少要进行 log2265=23.5 次比较。

Page 10: ACM 程序设计

示例— (HDOJ-1075)What Are You Talking About

题目描述: Ignatius is so lucky that he met a Martian yesterday. But he didn't know the language the Martians use. The Martian gives him a history book of Mars and a dictionary when it leaves. Now Ignatius want to translate the history book into English. Can you help him?

Page 11: ACM 程序设计

样本数据 (HDOJ-1075)Sample InputSTART from fiwo hello difh mars riwosf earth fnnvk like fiiwj END START difh, i'm fiwo riwosf. i fiiwj fnnvk! END

Sample Outputhello, i'm from mars.i like earth!

Input Description:All the words are in the lowercase, and each word will contain at most 10 characters, and each line will contain at most 3000 characters.

Page 12: ACM 程序设计

题目分析 (HDOJ-1075) 特点?数据量大 主要任务?查找单词 解决方法?字典树 字典树结构(除指针)?单词信息(英文) 额外提醒?字符串操作的熟练应用 其他问题? NO~

Page 13: ACM 程序设计

相关练习 HDOJ-1075 What Are You Talking Abou

t

HDOJ-1251 统计难题 HDOJ-1298 T9 HDOJ-1800 Flying to the Mars ZOJ-1109 Language of FatMouse

Page 14: ACM 程序设计

附 : 参考源码 (HDOJ-1251) #include "stdio.h" #include "string.h" #include "stdlib.h"

struct dictree { struct dictree *child[26]; int n; }; struct dictree *root;

void insert (char *source) { int len,i,j; struct dictree *current,*newnode; len=strlen(source); if(len==0) return; current=root; for(i=0;i<len;i++) { if(current->child[source[i]-'a']!=0) { current=current->child[source[i]-'a']; current->n=current->n+1; } else { newnode=(struct dictree *)malloc(sizeof(struct dictree)); for(j=0;j<26;j++) newnode->child[j]=0; current->child[source[i]-'a']=newnode; current=newnode; current->n=1; } } }

int find(char *source) { int i,len; struct dictree *current; len=strlen(source); if(len==0) return 0; current=root; for(i=0;i<len;i++) { if(current->child[source[i]-'a']!=0) current=current->child[source[i]-'a']; else return 0; } return current->n; } int main() { char temp[11]; int i,j; root=(struct dictree *)malloc(sizeof(struct dictree)); for(i=0;i<26;i++) root->child[i]=0; root->n=2; while(gets(temp),strcmp(temp,"")!=0) insert(temp); while(scanf("%s",temp)!=EOF) { i=find(temp); printf("%d\n",i); } }

Page 15: ACM 程序设计

Welcome to HDOJ

Thank You ~