• 字典树(增删改查 HDU 5687)


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

      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


    思路分析 : 字典树板子题,唯一有个要注意的地方就是删除操作,你要删除具有公共前缀的所有串,首先可以先计算出公共前缀的个数,然后再去处理一遍所要处理的串,给每个节点删除掉公共前缀的个数,
      将最后一个点的 val 变为 0 ,并且将其 next 全部变为 0即可。
    代码示例 :
    #define ll long long
    const int maxn = 1e6+5;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    
    struct node
    {
        int next[26];
        int val;
    }t[maxn];
    char f[20], s[50];
    int rt = 1;
    int num;
    
    void insert() {
        int u = 0, v;
        int len = strlen(s+1);
        
        for(int i = 1; i <= len; i++){
            v = s[i] - 'a';
            if (!t[u].next[v]) t[u].next[v] = rt++;
            u = t[u].next[v]; 
            t[u].val++;
        } 
    }
    
    void del() {
        int u = 0, v;
        int len = strlen(s+1);
        
        for(int i = 1; i <= len; i++){
            v = s[i] - 'a'; 
            u = t[u].next[v]; 
            t[u].val -= num;
        }
        t[u].val = 0;
        for(int j = 0; j < 26; j++) t[u].next[j] = 0;
    }
    
    int search() {
        int u = 0, v;
        int len = strlen(s+1);
        
        for(int i = 1; i <= len; i++){
            v = s[i] - 'a';
            if (!t[u].next[v]) return 0;
            u = t[u].next[v];
            //if (t[u].val == 0) return 0;
        }
        return t[u].val;
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int n;
        cin >> n;
        memset(t, 0, sizeof(t));
        while(n--){
            scanf("%s%s", f+1, s+1);
            if (f[1] == 'i') insert();
            else if (f[1] == 'd') {num = search(); if (num != 0) del();}
            else {
                if (search()) cout << "Yes" << endl;
                else cout << "No" << endl;
            }
        }
        return 0;
    }
    


    东北日出西边雨 道是无情却有情
  • 相关阅读:
    任务墙(6月3日)
    燃尽图(6月3日)
    6.1-6.2小结
    5月28日任务进展
    个人感悟
    代码评审
    如何用ZBrush确定头部五官的位置
    ZBrush中的纹理-水手该怎样进行绘制
    怎样对ZBrush中的材料进行渲染和着色
    快速熟悉Zbrush中的四种裁切笔刷
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8563505.html
Copyright © 2020-2023  润新知