字典树 增删查改变式

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

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

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

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

Input

这里仅有一组测试数据。第一行输入一个正整数N(1≤N≤100000)N(1≤N≤100000),代表度熊对于字典的操作次数,接下来NN行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: 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

在添加一个单词时,针对在字典树中这个单词经过的所有节点,都会flag+1,表示有多少单词经过它。

在删除一个单词时,先统计出这个单词出现的次数。然后在遍历节点时这个单词经过的所有节点都要减去这个次数。

注意递归删除和添加字典树的写法。

#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 26;
struct Trie
{
    Trie *Next[maxn];
    int flag;
    inline void init()
    {
        this->flag=1;
        for(int i=0; i<maxn; i++)
        {
            this->Next[i]=NULL;
        }
    }
};
Trie *root =(Trie*)malloc(sizeof(Trie));
inline void DelTrie(Trie * T)
{
    if(T==NULL)
        return ;
    for(int i=0; i<maxn; i++)
    {
        if(T->Next[i]!=NULL)
        {
            DelTrie(T->Next[i]);//递归删除节点
        }
    }
    free(T);
    return;
}
void createTrie(char *str,bool isDel)
{
    int len=strlen(str);//str是一个数组
    Trie *p=root,*temp;
    int DelNum=0;
    for(int i=0; i<len; i++)
    {
        int idx=str[i]-'a';
        if(!isDel)
        {
            if(p->Next[idx]==NULL)
            {
                temp=(Trie *)malloc(sizeof(Trie));
                temp->init();
                p->Next[idx]=temp;
                p=p->Next[idx];
            }
            else
            {
                p->Next[idx]->flag++;
                p=p->Next[idx];
            }
        }
        else
        {
            if(p->Next[idx]!=NULL)
            {
                DelNum=p->Next[idx]->flag;
                p=p->Next[idx];
            }
            else
            {
                return ;
            }
        }
    }
    if(isDel)
    {
        p=root;//删除情况
        for(int i=0; i<len; i++)
        {
            int idx=str[i]-'a';
            if(p->Next[idx]==NULL)
                return;
            if(i==len-1)
            {
                //终点
                DelTrie(p->Next[idx]);
                p->Next[idx]=NULL;//递归删除
                return ;
            }
            p->Next[idx]->flag-=DelNum;
            p=p->Next[idx];
        }
    }
}
bool FindStr(char *str)
{
    int len=strlen(str);
    Trie *p=root;
    for(int i=0; i<len; i++)
    {
        int idx=str[i]-'a';
        if(p->Next[idx]!=NULL&&p->Next[idx]->flag>0)
            p=p->Next[idx];
        else
            return false;
    }
    return true;
}
int main(void)
{
    root->init();
    int n;
    scanf("%d", &n);
    char command[7], str[33];
    while(n--)
    {
        scanf("%s", command);
        if(strcmp(command, "insert")==0)
        {
            scanf("%s", str);
            createTrie(str, false);
        }
        else if(strcmp(command, "delete")==0)
        {
            scanf("%s", str);
            createTrie(str, true);//删除的时候
        }
        else
        {
            scanf("%s", str);
            FindStr(str)?puts("Yes"):puts("No");
        }
    }
    DelTrie(root);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/87808090
今日推荐