Trie树

原创 2015年07月07日 09:40:04

在Trie树中主要有3个操作,插入、查找和删除。一般情况下Trie树中很少存在删除单独某个结点的情况,因此只考虑删除整棵树。

1.插入

  假设存在字符串str,Trie树的根结点为root。i=0,p=root。

  1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;

   若不为空,则p=p->next[str[i]-97];

  2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的isStr置为true。

2.查找

  假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root

  1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。

  2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且isStr为true,则返回true,否则返回false。

3.删除

  删除可以以递归的形式进行删除。

#include <iostream>
#include<cstdlib>
#define MAX 26
using namespace std;
 
typedef struct TrieNode                     //Trie结点声明 
{
    bool isStr;                            //标记该结点处是否构成单词 
    struct TrieNode *next[MAX];            //儿子分支 
}Trie;
 
void insert(Trie *root,const char *s)     //将单词s插入到字典树中 
{
    if(root==NULL||*s=='\0')
        return;
    int i;
    Trie *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'a']==NULL)        //如果不存在,则建立结点 
        {
            Trie *temp=(Trie *)malloc(sizeof(Trie));
            for(i=0;i<MAX;i++)
            {
                temp->next[i]=NULL;
            }
            temp->isStr=false;
            p->next[*s-'a']=temp;
            p=p->next[*s-'a'];   
        }   
        else
        {
            p=p->next[*s-'a'];
        }
        s++;
    }
    p->isStr=true;                       //单词结束的地方标记此处可以构成一个单词 
}
 
int search(Trie *root,const char *s)  //查找某个单词是否已经存在 
{
    Trie *p=root;
    while(p!=NULL&&*s!='\0')
    {
        p=p->next[*s-'a'];
        s++;
    }
    return (p!=NULL&&p->isStr==true);      //在单词结束处的标记为true时,单词才存在 
}
 
void del(Trie *root)                      //释放整个字典树占的堆区空间 
{
    int i;
    for(i=0;i<MAX;i++)
    {
        if(root->next[i]!=NULL)
        {
            del(root->next[i]);
        }
    }
    free(root);
}
 
int main(int argc, char *argv[])
{
    int i;
    int n,m;                              //n为建立Trie树输入的单词数,m为要查找的单词数 
    char s[100];
    Trie *root= (Trie *)malloc(sizeof(Trie));
    for(i=0;i<MAX;i++)
    {
        root->next[i]=NULL;
    }
    root->isStr=false;
    scanf("%d",&n);
    getchar();
    for(i=0;i<n;i++)                 //先建立字典树 
    {
        scanf("%s",s);
        insert(root,s);
    }
    while(scanf("%d",&m)!=EOF)
    {
        for(i=0;i<m;i++)                 //查找 
        {
            scanf("%s",s);
            if(search(root,s)==1)
                printf("YES\n");
            else
                printf("NO\n");
        }
        printf("\n");   
    }
    del(root);                         //释放空间很重要 
    return 0;
}


Hdu 1075

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX 30
typedef struct Trie   
{   
    Trie *next[MAX];   
    int v;   //根据需要变化
};   
 
Trie root;
char str[35000];
char len[35000];
void createTrie(char *str,int wei)
{
    int len = strlen(str);
    Trie *p = &root, *q;
    for(int i=0; i<len; ++i)
    {
        int id = str[i]-'a';
        if(p->next[id] == NULL)
        {
            q = (Trie *)malloc(sizeof(Trie));
            q->v = -1;    //把不是字符串最后一个的v 都初始化为-1
            for(int j=0; j<MAX; ++j)
                q->next[j] = NULL;
            p->next[id] = q;
            p = p->next[id];
        }
        else
        {
            p = p->next[id];
        }
    }
    p->v = wei;   //若为结尾,则将v改成wei表示这串字符串对应的字符串在arr中的下标
}

int findTrie(char *str)
{
    int len = strlen(str);
    Trie *p = &root;
    for(int i=0; i<len; ++i)
    {
        int id = str[i]-'a';
        p = p->next[id];
        if(p == NULL)   //已经找不到第i+1个字母了,所以不存在这个字符串
            return -1;
        if(p->v != -1&&i==len-1)   
            return p->v;
    }
    return -1;   //此串是字符集中某串的前缀
}
char arr[500000][15];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("output.txt","w",stdout);
#endif
    int n;
    scanf("%s",str);
    for(int i=0;;i++)
    {
        scanf("%s",arr[i]);
        if(strcmp(arr[i],"END")==0)
        {
            scanf("%s",arr[i]);
            break;
        }
        scanf("%s",str);
        createTrie(str,i);
    }
    getchar();
    char c;
    int p=0;
    while(1)
    { 
        gets(len);
        if(strcmp(len,"END")==0)
            break;
        int nn=strlen(len);
        len[nn]=10;//因为是gets输入没有回车,所以添加一个回车
        len[nn+1]=0;
        for(int i=0;len[i];i++)
        {
            c=len[i];
            if((c<='z'&&c>='a'))
                str[p++]=c;
            else
            {
                str[p]=0;
                int tem=findTrie(str);
                if(tem!=-1)
                    printf("%s%c",arr[tem],c);
                else 
                    printf("%s%c",str,c);
                p=0;
            }
        }
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

DoubleArrayTrie(双数组Trie树)

  • 2015-10-22 09:57
  • 2.13MB
  • 下载

trie树模板,acm竞赛

Trie树的学习

所写内容,是对自己所学知识的一个记录罢了。 1.简介 最近在做中国人名识别的时候,看到一篇文章是基于角色的人名识别,而角色字典中有2个角色是用双数组Tire树来建立的,当时没有看懂,于是来先学习T...

trie树实现英语词典

  • 2008-09-15 15:38
  • 200KB
  • 下载

Trie树

Trie树        Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。 一.Trie树的原理     利用串构建一个字...

Trie树 linux32 SDK V3.0

  • 2010-04-18 17:25
  • 238KB
  • 下载

Trie树——java

输入 输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词(不保证是英文单词,也有可能是火星文单词哦),单词由不超过10个的小写英文字母组成,可能存在相同的单词,此时应将其视作不同的...

Acm Trie树

  • 2014-04-06 10:28
  • 45KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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