出处:http://www.cnblogs.com/pony1993/archive/2012/07/18/2596730.html(秦神的博客)
字典树,又称单词查找树,Trie树,是一种树形结构,典型应用是用于统计,排序和保存大量的字符串,所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度的减少无谓的字符串比较,查询效率比哈希表高。
它有三个基本性质,根节点不包含字符,除根节点外每一个节点都只包含一个字符,从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串,每个节点的所有子节点包含的字符都不相同。

字典树的插入,删除和查找都非常简单,用一个一重循环即可。
1. 从根节点开始一次搜索
2. 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索
3. 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索
4. 迭代过程...
5. 在某个节点处,关键词的所有字母已被取出,则读取附在该节点上的信息,即完成查找
字典树的应用
1.字典树在串的快速检索中的应用。
给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。
在这道题中,我们可以用数组枚举,用哈希,用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。
2. 字典树在“串”排序方面的应用
给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出
用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可
3. 字典树在最长公共前缀问题的应用
对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为最近公共祖先问题。
1. 从根节点开始一次搜索
2. 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索
3. 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索
4. 迭代过程...
5. 在某个节点处,关键词的所有字母已被取出,则读取附在该节点上的信息,即完成查找
字典树的应用
1.字典树在串的快速检索中的应用。
给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。
在这道题中,我们可以用数组枚举,用哈希,用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。
2. 字典树在“串”排序方面的应用
给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出
用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可
3. 字典树在最长公共前缀问题的应用
对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为最近公共祖先问题。
字典树的基本功能是用来查询某个单词(前缀)在所有单词中出现次数的一种数据结构,它的插入和查询复杂度都为O(len),Len为单词(前缀)长度,但是它的空间复杂度却非常高,如果字符集是26个字母,那每个节点的度就有26个,典型的以空间换时间结构。
基本模版
1、结构体定义:
struct node
{
int flag;//标记变量
int count;//记录字符出现次数
struct node *next[N];
}tree[maxn];
2、新节点建立
3、插入
4、查找
int search(struct node **root,char *s)
{
int i=0,k;
struct node *p;
if(!(p=*root))
{
return 0;
}
while(s[i])
{
k=s[i++]-'a';
if(!(p->next[k]))
return 0;
p=p->next[k];
}
return p->flag;//return p->count;
}
杭电模版题 HDU 1247 Hat's Words http://acm.hdu.edu.cn/showproblem.php?pid=1247
#include <iostream>
#include <cstring>
#include <cstdio>
const int N=26;
const int maxn=1000000;
char s[50001][101];
using namespace std;
struct node
{
int flag;
int count;
struct node *next[N];
}tree[maxn];
int t=0;
struct node *creat()
{
int i;
struct node *p;
p=&tree[t++];
p->count=1;
p->flag=0;
for(i=0;i<N;i++)
{
p->next[i]=NULL;
}
return p;
}
void insert(struct node **root,char *s)
{
int i,k;
struct node *p;
if(!(p=*root))
{
p=*root=creat();
}
i=0;
while(s[i])
{
k=s[i++]-'a';
if(p->next[k])
p->next[k]->count++;
else
p->next[k]=creat();
p=p->next[k];
}
p->flag=1;
}
int search(struct node **root,char *s)
{
int i=0,k;
struct node *p;
if(!(p=*root))
{
return 0;
}
while(s[i])
{
k=s[i++]-'a';
if(!(p->next[k]))
return 0;
p=p->next[k];
}
return p->flag;
}
int main()
{
char s1[101],s2[101],s3[101];
int l,i,j,k,c=0;
struct node *root=NULL;
while(~scanf("%s",s[c]))
{
insert(&root,s[c]);
c++;
}
for(i=0;i<c;i++)
{
memset(s1,0,sizeof(s1));
l=strlen(s[i]);
for(j=0;j<l;j++)
{
s1[j]=s[i][j];
if(search(&root,s1))
{
memset(s2,0,sizeof(s2));
for(k=j+1;k<l;k++)
s2[k-j-1]=s[i][k];
if(search(&root,s2))
{
puts(s[i]);
break;
}
}
}
}
return 0;
HDU 1075 What Are You Talking About
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
const int N=26;
const int maxn=3007;
struct node
{
int flag;
char t[11];
struct node *next[N];
};
struct node *creat()
{
int i;
struct node *p=new (struct node);
p->flag=0;
for(i=0;i<N;i++)
{
p->next[i]=NULL;
}
return p;
}
void insert(struct node **root,char *s,char *s1)
{
int i,k;
struct node *p;
if(!(p=*root))
{
p=*root=creat();
}
i=0;
while(s[i])
{
k=s[i++]-'a';
if(p->next[k]==NULL)
p->next[k]=creat();
p=p->next[k];
}
p->flag=1;
strcpy(p->t, s1);
}
int search(struct node **root,char *s,char *s1)
{
int i=0,k;
struct node *p;
if(!(p=*root))
{
return 0;
}
while(s[i])
{
k=s[i++]-'a';
if(!(p->next[k]))
return 0;
p=p->next[k];
}
if(p->flag)
{
strcpy(s1, p->t);
return 1;
}
return 0;
}
int main()
{
int i,j,l,k,len;
struct node *root=NULL;
char s[11],s1[11],s2[11];
while(~scanf("%s",s))
{
if(!strcmp(s,"END"))
break;
if(strcmp(s,"START"))
{
scanf("%s",s2);
insert(&root,s2,s);
}
}
getchar();
char line[maxn];
while(gets(line))
{
if(!strcmp(line,"END"))
break;
if(strcmp(line,"START"))
{
len=strlen(line);
k=0;
memset(s,0,sizeof(s));
for(i=0;i<len;i++)
{
if(islower(line[i]))
{
s[k++]=line[i];
if(i==len-1)
{
memset(s1,0,sizeof(tm));
if(search(&root,s,s1))
{
l=strlen(s1);
for(j=0;j<l;j++)
printf("%c",s1[j]);
}
else
{
for(j=0;j<k;j++)
printf("%c",s[j]);
}
break;
}
}
else
{
memset(s1,0,sizeof(s1));
if(search(&root,s,s1))
{
l=strlen(s1);
for(j=0;j<l;j++)
printf("%c",s1[j]);
}
else
for(j=0;j<k;j++)
printf("%c",s[j]);
printf("%c",line[i]);
k=0;
memset(s,0,sizeof(s));
}
}
puts("");
}
memset(line,0,sizeof(line));
}
return 0;
}
POJ模版题 POJ 3630 Phone List http://poj.org/problem?id=3630
#include <iostream>
#include <cstring>
#include <cstdio>
const int N=11;
const int maxn=1000001;
int flag;
using namespace std;
struct node
{
int flag;
int count;
struct node *next[N];
}tree[maxn];
int t=0;
struct node *creat()
{
int i;
struct node *p;
p=&tree[t++];
p->count=1;
p->flag=0;
for(i=0;i<N;i++)
{
p->next[i]=NULL;
}
return p;
}
void insert(struct node **root,char *s)
{
int i,k,l;
struct node *p;
if(!(p=*root))
{
p=*root=creat();
}
l=strlen(s);
for(i=0;i<l;i++)
{
k=s[i]-'0';
if(p->next[k]&&i==l-1)
{
flag=1;
return;
}
if(p->next[k])
{
if(p->next[k]->flag)
{
flag=1;
return;
}
}
else
p->next[k]=creat();
p=p->next[k];
}
p->flag=1;
}
int search(struct node **root,char *s)
{
int i=0,k;
struct node *p;
if(!(p=*root))
{
return 0;
}
while(s[i])
{
k=s[i++]-'0';
if(!(p->next[k]))
return 0;
p=p->next[k];
}
return p->flag;
}
int main()
{
char s1[N];
int t,i,c;
scanf("%d",&t);
while(t--)
{
flag=0;
struct node *root=NULL;
scanf("%d%*c",&c);
for(i=0;i<c;i++)
{
scanf("%s",s1);
if(!flag)
{
insert(&root,s1);
}
}
if(flag)
puts("NO");
else
puts("YES");
}
return 0;
}