hdu-5687(字典树)

题意:中文题;

解题思路:增加和查询就不说了,标准操作,就是删除操作:删除操作的时候,我们把给定字符串先在字典树中遍历一遍,然后算出这个字符串最后一个字符的出现次数,然后在遍历一遍,每个节点都减去这个次数,最后节点的儿子全部归零;

最开始我是只考虑的最后节点,中间节点都没考虑,这样会出现一个问题就是:插入abdefg,删除abcd的时候,查询abc还是会有答案,所有中间过程也得减去;

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1200500
using namespace std;
int trie[maxn][26];
int num[maxn]={-1};
int root;
int tot;
int t,n;
void init()
{
    memset(trie,0,sizeof(trie));
    memset(num,0,sizeof(num));
    tot=0;
}
void get_trie(char *s)
{
    root=0;
    int slen=strlen(s);
    for(int i=0;i<slen;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id])
        {
            trie[root][id]=++tot;
        }
        root=trie[root][id];
        num[root]++;
    }
}
int query(char *s)
{
    root=0;
    int slen=strlen(s);
    for(int i=0;i<slen;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id])
        {
            return 0;
        }
        root=trie[root][id];
    }
    return num[root];
}
void delete_trie(char *s)
{
    root=0;
    int cnt=0;
    int slen=strlen(s);
    for(int i=0;i<slen;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id])
        {
            return;
        }
        root=trie[root][id];
    }
    cnt=num[root];
    root=0;
    for(int i=0;i<slen;i++)
    {
        int id=s[i]-'a';
        root=trie[root][id];
        num[root]=num[root]-cnt;
    }
    for(int i=0;i<=25;i++)
    trie[root][i]=0;
}
int main()
{
    char s[10],a[50];
    scanf("%d",&t);
    init();
    while(t--)
    {
        scanf("%s",s);
        scanf("%s",a);
        if(s[0]=='i')
        {
            get_trie(a);
        }
        else if(s[0]=='s')
        {
            int flag=query(a);
            if(flag==0)
                printf("No\n");
            else
                printf("Yes\n");
        }
        else
        {
            delete_trie(a);
        }
    }
}

  

posted @ 2018-08-23 16:10  荒岛的龟  阅读(399)  评论(1编辑  收藏  举报