HDU-5687 Problem C(2016"百度之星"-资格赛)

Problem C

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


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

题解:字典树裸题,每次插入单词就把相应的字符的出现次数+1,删除的时候把前缀的所有字符的出现次数减去最后一个字符的出现次数,

如果为负数,则变成0,表示该位置上没有这个字符

#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e6 + 5;
struct node{
    int nxt[26];
    int v;  //记录字符出现次数
    void Init(){
        for(int i=0;i<26;i++) nxt[i]=-1;
        v=0;
    }
}L[maxn];
int tot=0;
void add(char a[]){
    int len=strlen(a),now=0;
    for(int i=0;i<len;i++){
        int tmp=a[i]-'a';
        if(L[now].nxt[tmp]==-1){
            L[++tot].Init();
            L[now].nxt[tmp]=tot;
        }
        now=L[now].nxt[tmp];
        L[now].v++;
    }

}
/*
本来很天真的以为只要从前缀的最后一个字符删去就等于删除所有有前缀的字符了,WA了无数次.
void delet(char a[]){
    int len=strlen(a),now=0;
    for(int i=0;i<len-1;i++){
        int tmp=a[i]-'a';
        if(L[now].nxt[tmp]==-1) return;
        now=L[now].nxt[tmp];
    }
    int tmp=a[len-1]-'a';
    L[now].nxt[tmp]=-1;
}
*/
void delet(char a[]){
    int len=strlen(a),now=0;
    for(int i=0;i<len;i++){
        int tmp=a[i]-'a';
        if(L[now].nxt[tmp]==-1) return;
        now=L[now].nxt[tmp];
    }
    int cnt=L[now].v;
    L[now].Init();
    now=0;
    for(int i=0;i<len;i++){
        int tmp=a[i]-'a';
        L[now].v-=cnt;
        L[now].v=L[now].v>0?L[now].v:0;   //如果出现次数为负,则改成0
        now=L[now].nxt[tmp];
    }
}
int Search(char a[]){
    int len=strlen(a),now=0;
    for(int i=0;i<len;i++){
        int tmp=a[i]-'a';
        if(L[now].nxt[tmp]==-1) return 0;
        now=L[now].nxt[tmp];
        if(L[now].v<=0) return 0;   //该字符没有出现,表示没有该前缀,返回0
    }
    return 1;
}
int main(){
    int n;
    char op[15],st[55];
    L[0].Init();
  //  freopen("in.txt","r",stdin);
    scanf("%d",&n);
    tot=0;
    while(n--){
        scanf("%s",op);
        scanf("%s",st);
        if(op[0]=='i') add(st);
        else if(op[0]=='d') delet(st);
        else {
            if(Search(st)) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值