zoukankan      html  css  js  c++  java
  • HDU1251 统计难题

    题意

    给定很多个单词后, 统计以某个字符串为前缀的单词数量(单词本身也是自己的前缀).

    题解

    一道字典树的裸题, 对于单词只有小写字母的情况, 字典树相当于一颗 26 叉树, 每个节点的构成是这样的

    struct Trie {
      	// ARRSIZE个指向孩子节点的指针
        Trie* next[ARRSIZE];
        int cnt;
        Trie() {
            for(int i = 0; i < ARRSIZE; i++)
                next[i] = 0;
          	// 注意, 此处是统计以父亲节点为结尾的前缀个数.
            cnt = 0;
        }
    };
    

    主要操作有 插入查询 节点

    插入

    1. 按位寻找字母所代表的下标在next 数组中的值是否为空.

      若为空, 则创建新的节点.

    2. 将指针移向下标所指节点, 进行 cnt++ 操作

      重复第一步操作, 直至遍历完成整个需要插入的字符串;

    void insertWord(Trie* root, string str) {
        Trie* p = root;
        for(int i = 0; i < str.size(); i++) {
            int index = (str[i] - 'a');
            if(!p->next[index]) {
                p->next[index] = new Trie();
            }
            p = p->next[index];
            p->cnt++;
        }
    }
    

    查询

    对于查询前缀操作, 需要注意的一点是 查询的前缀可能根本不存在

    代码如下

    int searchPrefix(Trie* root, string str) {
        Trie* pCrawl = root;
        for(int i = 0; i < str.size(); i++) {
            int index = str[i] - 'a';
            pCrawl = pCrawl->next[index];
            //和上一句的顺序很重要
            if(pCrawl == NULL)
                return 0;
        }
        return pCrawl->cnt;
    }
    

    此处需要特别注意 pCrawl 和 pCrawl->next[index] 的检查方法, 对于样例中的 abc 来说, 由于输入中 abs 是存在 的, 因此指向 b 的 儿子 的是不为空的, 但 pCrwal->next['c' - 'a'] 的值为NULL. 由于 字符c 在串的最后一个, 所以会造成 return NULL->cnt 的错误

    AC 代码

    #include <cstdio>
    #include <string>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    const int ARRSIZE = 26;
    struct Trie {
        Trie* next[ARRSIZE];
        int cnt;
        Trie() {
            for(int i = 0; i < ARRSIZE; i++)
                next[i] = 0;
            cnt = 0;
        }
    };
    void insertWord(Trie* root, string str) {
        Trie* p = root;
        for(int i = 0; i < str.size(); i++) {
            int index = (str[i] - 'a');
            if(!p->next[index]) {
                p->next[index] = new Trie();
            }
            p = p->next[index];
            p->cnt++;
        }
    }
    int searchPrefix(Trie* root, string str) {
        Trie* pCrawl = root;
        for(int i = 0; i < str.size(); i++) {
            int index = str[i] - 'a';
            pCrawl = pCrawl->next[index];
            //和上一句的顺序很重要
            if(pCrawl == NULL)
                return 0;
        }
        return pCrawl->cnt;
    }
    int main() {
        Trie* root = new Trie();
        while(true) {
            string str; getline(cin, str);
            if(str == "")
                break;
            insertWord(root, str);
        }
        string str;
        while(cin >> str) {
            cout << searchPrefix(root, str) << endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    难找的对象
    欺负10086客服小姐(超搞笑)
    左手,请握紧你的右手!
    Discuz! 6.x/7.x EXP
    【超搞视频】  另类乞讨让你笑掉大牙 !
    GNU/Linux平台的C程序开发及程序运行环境
    SICK LMS200激光数据采集程序说明
    郭云深划分武学境界
    Discuz XSS得webshell
    200条装修小常识(结婚,不结婚的都要看一下,很有用的)
  • 原文地址:https://www.cnblogs.com/1pha/p/8719248.html
Copyright © 2011-2022 走看看