字典树

转载 2011年01月10日 13:43:00

字典树:

http://www.cnblogs.com/DiaoCow/archive/2010/04/19/1715337.html

 

字典树的基本功能是用来查询某个单词(前缀)在所有单词中出现次数的一种数据结构,它的插入和查询复杂度都为O(len),Len为单词(前缀)长度,但是它的空间复杂度却非常高,如果字符集是26个字母,那每个节点的度就有26个,典型的以空间换时间结构

模板代码:

#define  MAX    26 //字符集大小

typedef
struct TrieNode
{
   
int nCount; //记录该字符出现次数
    struct TrieNode *next[MAX];
}TrieNode;

TrieNode Memory[
1000000];
int allocp = 0;

/*初始化*/
void InitTrieRoot(TrieNode **pRoot)
{
   
*pRoot = NULL;
}

/*创建新结点*/
TrieNode
*CreateTrieNode()
{
   
int i;
    TrieNode
*p;

    p
= &Memory[allocp++];
    p
->nCount = 1;
   
for(i = 0 ; i < MAX ; i++)
    {
        p
->next[i] = NULL;
    }

   
return p;
}

/*插入*/
void InsertTrie(TrieNode **pRoot , char *s)
{
   
int i , k;
    TrieNode
*p;

   
if(!(p = *pRoot))
    {
        p
= *pRoot = CreateTrieNode();
    }
    i
= 0;
   
while(s[i])
    {
        k
= s[i++] - 'a'; //确定branch
        if(p->next[k])
            p
->next[k]->nCount++;
       
else
            p
->next[k] = CreateTrieNode();
        p
= p->next[k];
    }
}

//查找
int SearchTrie(TrieNode **pRoot , char *s)
{
    TrieNode
*p;
   
int i , k;

   
if(!(p = *pRoot))
    {
       
return 0;
    }
    i
= 0;
   
while(s[i])
    {
        k
= s[i++] - 'a';
       
if(p->next[k] == NULL)    return 0;
        p
= p->next[k];
    }
   
return p->nCount;
}

 

 

典型例题:

1.统计难题(这里都用数组分配结点,用malloc分配太慢了)
这题就是统计一组字符串中某前缀出现次数(字典树第一类应用),因此只要简单的套模板就行了(在节点中设置一个成员变量nCount,来记录该字符出现次数)

#include <stdio.h>
#define  MAX    26

typedef
struct TrieNode
{
   
int nCount;
   
struct TrieNode *next[MAX];
}TrieNode;

TrieNode Memory[
1000000];
int allocp = 0;

void InitTrieRoot(TrieNode **pRoot)
{
   
*pRoot = NULL;
}

TrieNode
*CreateTrieNode()
{
   
int i;
    TrieNode
*p;

    p
= &Memory[allocp++];
    p
->nCount = 1;
   
for(i = 0 ; i < MAX ; i++)
    {
        p
->next[i] = NULL;
    }

   
return p;
}

void InsertTrie(TrieNode **pRoot , char *s)
{
   
int i , k;
    TrieNode
*p;

   
if(!(p = *pRoot))
    {
        p
= *pRoot = CreateTrieNode();
    }
    i
= 0;
   
while(s[i])
    {
        k
= s[i++] - 'a'; //确定branch
        if(p->next[k])
            p
->next[k]->nCount++;
       
else
            p
->next[k] = CreateTrieNode();
        p
= p->next[k];
    }
}

int SearchTrie(TrieNode **pRoot , char *s)
{
    TrieNode
*p;
   
int i , k;

   
if(!(p = *pRoot))
    {
       
return 0;
    }
    i
= 0;
   
while(s[i])
    {
        k
= s[i++] - 'a';
       
if(p->next[k] == NULL)    return 0;
        p
= p->next[k];
    }
   
return p->nCount;
}
   
int main(void)
{
   
char s[11];   
   
    TrieNode
*Root = NULL;  
    InitTrieRoot(
&Root);   
   
while(gets(s) && s[0]) 
    {      
        InsertTrie(
&Root , s);
    }   

   
while(gets(s))  
    {       
        printf(
"%d/n", SearchTrie(&Root , s));  
    }    
  

2.Phone List

这道题就是判断一组字符串中是否有一个字符串是另一个字符串的前缀(字典树第二类应用)。

分析:我们只要在结点中添加一个nEndFlag成员变量即可。若nEndFlag == 1,说明该结点字符是某一字符串的结尾(假设为A),若在插入B字符串的过程中经过这一结点,则说明A是B的前缀;还有一种情况,当要插入最后一个字符c时,却发现p->next[c-'0']为真,则说明该字符串是一个前缀字符串,eg:先插入abcde,再插入abc这种情况

return    0;
}

 

#include <stdio.h>
#define  MAX    10

typedef
struct TrieNode
{
   
int nEndFlag; //标记该字符是否是某一字符串的结尾
    struct TrieNode *next[MAX];
}TrieNode;

TrieNode Memory[
1000000];
int allocp = 0 , nFlag = 0;

void InitTrieRoot(TrieNode **pRoot)
{
   
*pRoot = NULL;
}

TrieNode
*CreateTrieNode()
{
   
int i;
    TrieNode
*p;

    p
= &Memory[allocp++];
    p
->nEndFlag = 0;
   
for(i = 0 ; i < MAX ; i++)
    {
        p
->next[i] = NULL;
    }

   
return p;
}

void InsertTrie(TrieNode **pRoot , char *s)
{
   
int i , k;
    TrieNode
*p;

   
if(!(p = *pRoot))
    {
        p
= *pRoot = CreateTrieNode();
    }
    i
= 0;
   
while(s[i])
    {
        k
= s[i++] - '0';
       
if(p->next[k])
        {
           
if(p->next[k]->nEndFlag == 1 || s[i] == '/0') //先短后长 || 先长后短
            {
                nFlag
= 1;
               
return;
            }
        }
       
else
        {
            p
->next[k] = CreateTrieNode();
        }
        p
= p->next[k];
    }
    p
->nEndFlag = 1//标记结尾
}


int main(void)
{
   
int  z , n , i;
   
char s[11];   
    TrieNode
*Root; 

    scanf(
"%d", &z);
   
while(z-- > 0
    {      
        nFlag
= allocp = 0;
        InitTrieRoot(
&Root);
        scanf(
"%d" , &n);    getchar();
       
for(i = 0 ; i < n ; i++)
        {
            gets(s);
           
if(!nFlag)    InsertTrie(&Root , s);
        }
        nFlag
? printf("NO/n") : printf("YES/n");
    }   
 
   
return    0;
}
  
   

 

字典树数组实现

字典树是一种很实用也相对好理解的数据
  • u013588639
  • u013588639
  • 2014年08月06日 21:04
  • 1572

《字典树》数组模版

#include #include using namespace std; const int N=1000005; int trie[N][26],cnt[N],flag[N],num; vo...
  • a709743744
  • a709743744
  • 2016年01月26日 21:05
  • 492

字典树(Trie树)用法及例子(一)

字典树(Trie)概述字典树,又名Trie树。顾名思义,在字典中很好用。我们在查牛津词典时都是先按第一个字母找到以这个字母为首的单词所在的初始位置,在此位置的基础上,再按照第二个字母继续找。。。 插...
  • u010902721
  • u010902721
  • 2015年05月15日 20:53
  • 4313

字典树 c++ 实现

字典树 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。 典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串), 所以经常被搜索引擎系统用于文本词频统计。它...
  • rongdongzhu1
  • rongdongzhu1
  • 2015年09月13日 16:16
  • 1053

[算法系列之二十]字典树(Trie)

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。二 优点利用字符串的公共前缀来减...
  • SunnyYoona
  • SunnyYoona
  • 2015年02月21日 22:26
  • 4144

字典树的题目 找了个时间刷了一点字典树的题目

http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/2009/pid/2828 #includ...
  • qq_33435265
  • qq_33435265
  • 2017年04月26日 09:24
  • 241

01字典树 小结

为了做13年南京网络赛的一道题 学了这个01字典树 看了别人的模板 之后切了几道水题 现在总结一下01字典树的实现可以看成是把一个数的二进制字符化后插入到一颗一般的字典树中比如在01字典树种插入...
  • SolarDomo
  • SolarDomo
  • 2016年08月10日 10:15
  • 1296

空间优化的字典树

(同步个人博客 http://sxysxy.org/blogs/29 到csdn)字典树空间优化如果字典树要储存的字符串的字符集比较大,(比如全部的字符),甚至可能有多字节字符。这是我们给每个节点25...
  • u013632138
  • u013632138
  • 2016年09月08日 18:40
  • 244

hdu2846(字典树好题)

字典树的好题 题意:给你n个串,然后又q次询问,输出n个串中包含改串的个数 思路:这题非常考验个人的分析能力,最初的想法是用AC自动机或者是后缀数组做,但有感觉不可行,最后看了题解才知道要用字典树...
  • u013509299
  • u013509299
  • 2014年08月02日 22:54
  • 673

字典树简介和简易应用

1、背景         词汇搜索、词频统计等字符串操作,是搜索引擎、文本处理系统等经常使用的业务,现在假设有这么一个简单的文本处理例子:有一篇10000个词的文章,要查出单词“was”在这篇文章中出...
  • ly01kongjian
  • ly01kongjian
  • 2013年03月31日 16:15
  • 4022
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:字典树
举报原因:
原因补充:

(最多只允许输入30个字)