hdu 5687 Problem C

本文介绍了一个基于字典树实现的神奇字典,支持插入、删除和查询操作。通过实例演示了如何利用字典树高效地处理字符串集合,并提供了一种优化的节点管理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description

度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:

1、insert : 往神奇字典中插入一个单词

2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词

3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串

Input

这里仅有一组测试数据。第一行输入一个正整数N(1≤N≤100000),代表度熊对于字典的操作次数,接下来N行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: insert, delete 或者 search)。第二个字符串代表了相关操作后指定的那个字符串,第二个字符串的长度不会超过30。第二个字符串仅由小写字母组成。

Output

对于每一个search 操作,如果在度熊的字典中存在给定的字符串为前缀的单词,则输出Yes 否则输出 No。

Sample Input
5
insert hello
insert hehe
search h
delete he
search hello
Sample Output

Yes

No

自己思路:删除时,把没有单词的节点全部删除(节点没有必要删除,因为以后也可以用到这个节点)。大神思路:用num记录以当时节点为前缀的单词数,删除时就不用删除节点,只需要改变num,省时省空间,搜索时也是看num值。

字典树基础题,第一次敲字典树:

#include <iostream>
#include<string.h>
#include<stdio.h>
#define siz 500005
using namespace std;
int Trie[siz][27],sz,val[siz];
char str1[15],str2[35];
void Insert(char *s)
{
    int u=0,j;
    for(int i=0; s[i]; i++)
    {
        j=s[i]-'a';
        if(!Trie[u][j])
        {
            val[sz]=0;
            Trie[u][j]=sz++;
        }
        u=Trie[u][j];
    }
    val[u]=1;
}
bool Search(char *s)
{
    int u=0,j;
    for(int i=0; s[i]; i++)
    {
        j=s[i]-'a';
        if(!Trie[u][j])
            return false;
        u=Trie[u][j];
    }
    return true;
}
void Delete(char *s)
{
    int u=0,j,preu[35],prej[35],r=0;
    preu[0]=0;
    for(int i=0; s[i]; i++)
    {
        j=s[i]-'a';
        prej[r]=j;
        if(!Trie[u][j]) return;
        u=Trie[u][j];
        preu[++r]=u;
    }
    memset(Trie[u],0,sizeof(Trie[u]));
    for(int i=r-1; i>=0; i--)
    {
        u=preu[i], j=prej[i];
        Trie[u][j]=0;
        if(val[u]) return;
        for(int t=0; t<27; t++) if(Trie[u][t]) return;
    }
}
int main()
{
    int n;
    sz=1;
    scanf("%d",&n);
    for(int t=1; t<=n; t++)
    {
        scanf("%s %s",str1,str2);
        if(str1[0]=='i')
        {
            Insert(str2);
        }
        if(str1[0]=='s')
        {
            if(Search(str2))
            {
                cout<<"Yes"<<endl;
            }
            else
            {
                cout<<"No"<<endl;
            }
        }
        if(str1[0]=='d')
        {
            Delete(str2);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值