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;
}

posted @ 2018-04-04 20:55  1pha  阅读(124)  评论(0编辑  收藏  举报