字典树

  字典树

1.创建


struct Trie 

    // 代表当前节点可以延伸出的边,数量可变 

    Trie *Next[MAXN]; 

    // 标记当前节点是否是保存信息的结尾,也可以代表前缀个数 

    int Flag; 

    Trie() 

    { 

        // 初始化以该信息为前缀的信息个数 

        Flag = 1; 

        memset(Next, NULL, sizeof(Next)); 

    } 

}*root; 


2.插入

void Insert(char *str)  { 

    int len = strlen(str); 

    Trie *p = root, *q; 

    // 将str的每一个字符插入trie树 

    for(int i=0; i<len; ++i)   { 

        int id = str[i] - 'a'; 

        // 如果没有边,则新建一个trie节点,产生一条边,用以代表该字符 

        if(p->Next[id] == NULL)    { 

            q = new Trie(); 

            p->Next[id] = q; 

            p = p->Next[id];  } 

        // 如果存在边,则沿着该边走 

        else   { 

            p = p->Next[id]; 

            // 累加以该信息为前缀的信息个数 

            ++(p->Flag);  }   } } 




3.查找


int Query(char *str) 

    int len = strlen(str); 

    Trie *p = root; 

    // 在trie树上顺序搜索str的每一个字符 

    for(int i=0; i<len; ++i) 

    { 

        int id = str[i] - 'a'; 

        p = p->Next[id]; 

        // 若为空集,表示不存以此为前缀的信息 

        if(p == NULL) return 0; 

    } 

    // 返回以该信息为前缀的信息个数 

    return p->Flag; 



4.删除


void Free(Trie* T) 

    if(T == NULL) return; 

    // 释放trie树的每一个节点占用的内存 

    for(int i=0; i<MAXN; ++i) 

    { 

        if(T->Next[i]) Free(T->Next[i]); 

    } 

    delete(T); 


例 1  hdu 1247

Hat’s Words


题意: 给出多个按字典序的单词,输出字典序 的符合要求的单词,要求为该单词可以由两个已有的单词拼成,即前缀和后缀都为已知单词


代码


#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 26
struct Trie
{
    Trie *Next[MAXN];
    bool tf;
}*root;
char s[50000][50];
void Insert(char* str)
{
    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 = new Trie();
                for(int j=0;j<MAXN;j++)
    {
        q->Next[j]=NULL;
    }
    q->tf=false;
            p->Next[id] = q;
            p = p->Next[id];
        }
        else
        {
            p = p->Next[id];
        }
    }
    p->tf=true;
}
bool Querry(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)
            return false;
    }
    return p->tf;
}
void Free(Trie *T)
{
    if (T == NULL)
        return;
    for (int i = 0; i<MAXN; i++)
    {
        if (T->Next[i])
            Free(T->Next[i]);
    }
    delete(T);
}
int main()
{
    int coun=0,i,j;
    root = new Trie;
    for(i=0;i<MAXN;i++)
    {
        root->Next[i]=NULL;
    }
    root->tf=false;
        while(scanf("%s",s[coun])!=EOF)
        {
                Insert(s[coun]);
        coun++;
        }
    for(i=0;i<coun;i++)
    {  
     char temp1[50]={'\0'};
     char temp2[50]={'\0'};
        for(j=1;j<strlen(s[i]);j++)   
        {
            strcpy(temp1,s[i]);
            temp1[j]='\0';
            strcpy(temp2,s[i]+j);
            if(Querry(temp1)&&Querry(temp2))
            {
                printf("%s\n",s[i]);
                break;                      
            }
        }
    }
    Free(root);
    return 0;
}


例 2 hdu 1251  统计难题

 题意: 输入多个单词 ,再输入一些前缀,输出 有该前缀的单词个数  。纯字典树 ,套模板

代码:


#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
#define MAXN 26
struct Trie
{
    Trie *Next[MAXN];
    int Flag;
    Trie()
    {
        memset(Next,NULL,sizeof(Next));
        Flag=1;
     }
}*root;
void Insert(char* str)
{
    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 = new Trie();
            p->Next[id] = q;
            p = p->Next[id];
        }
        else
        {
            p = p->Next[id];
            ++(p->Flag);
        }
    }
}
int Querry(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)
            return 0;
    }
    return p->Flag;
}
void Free(Trie *T)
{
    if (T == NULL)
        return;
    for (int i = 0; i<MAXN; i++)
    {
        if (T->Next[i])
            Free(T->Next[i]);
    }
    delete(T);
}
int main()
{
    root = new Trie;
    char a[11];
        while(gets(a)&&a[0])
        {
            Insert(a);
        }
        while(gets(a))
        {
             cout<<Querry(a)<<endl;    
        }
    Free(root);
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值