HDOJ5687 字典树模板,数组实现

本文介绍了一个关于字典树的数据结构问题,通过一个具体的编程实例展示了如何使用C++实现字典树的基本操作,包括插入、搜索和删除带有特定前缀的单词。

Problem C

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1673    Accepted Submission(s): 482


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

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

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

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

Input
这里仅有一组测试数据。第一行输入一个正整数 N(1N100000) ,代表度熊对于字典的操作次数,接下来 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
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6107  6106  6105  6104  6103 


题意大家都懂的,就是个很裸的字典树题目。现在用数组写一个模板程序,供参考。
#include <iostream>
#include <cstdio>
#include <ctime>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn =3e6+10; //命令行数是100000,字符串长度不超过30,上限就是3e6
struct node {
      int next[26]; //只考虑小写字母的情况,大写的话扩大到52,有数字的话扩大到62
      int sum;
      void init(){
          sum=0;
          memset(next,-1,sizeof(next));
      }
};
node word[maxn];
int tot=0;

void add(char a[], int len){
    int now=0;
    for (int i=0; i<len;i++){
        int tmp=a[i]-'a';
        if (word[now].next[tmp]==-1){
            int x=tot++;
            word[x].init();
            word[now].next[tmp]=x;
        }
        now=word[now].next[tmp];
        word[now].sum+=1;
    }
}

int query(char a[] , int len){
   int now = 0;
   for (int i=0;i<len;i++){
      int tmp=a[i]-'a';
      if (word[now].next[tmp]==-1) return 0;
      now = word[now].next[tmp];
   }
   return word[now].sum;
}

void del(char a[] , int len , int cnt){
     int now=0;
     for (int i=0;i<len;i++){
        int tmp=a[i]-'a';
        if (word[now].next[tmp]==-1) return;
        word[now].sum-=cnt;
        now=word[now].next[tmp];
     }
     word[now].sum=0; //字符串最后一个字母对应的节点也要清除
     for (int i=0;i<26;i++) word[now].next[i]=-1;
}


int main(){
    std::ios::sync_with_stdio(false); //提高读入效率
    int n;
    char str[10],s[40];
    cin>>n;
    tot=1;
    while (n--){
        cin>>str>>s;
        if (str[0]=='s'){
              int ans=query(s,strlen(s));
              if (ans) cout<<"Yes"<<endl;
              else cout<<"No"<<endl;
        }
        else if (str[0]=='i'){
               add(s,strlen(s));
        }
        else {
            int ans = query(s,strlen(s));
            del(s,strlen(s),ans);
        }
    }
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值