每日一题之 hiho1014 Trie树 (字典树)

输入
输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词(不保证是英文单词,也有可能是火星文单词哦),单词由不超过10个的小写英文字母组成,可能存在相同的单词,此时应将其视作不同的单词。接下来的一行为一个正整数m,表示小Hi询问的次数,其后m行,每一行一个字符串,该字符串由不超过10个的小写英文字母组成,表示小Hi的一个询问。

在20%的数据中n, m<=10,词典的字母表大小<=2.

在60%的数据中n, m<=1000,词典的字母表大小<=5.

在100%的数据中n, m<=100000,词典的字母表大小<=26.

输出
对于小Hi的每一个询问,输出一个整数Ans,表示词典中以小Hi给出的字符串为前缀的单词的个数。

思路:

字典树模版,维护一棵26叉树,遍历每个单词的每个字母进行建树。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>

using namespace std;

const int maxn = 30;

typedef struct Trie 
{
     Trie *next[maxn]; //下一层的节点数(小写字母个数)
     int v; //从根节点到当前节点为前缀的单词个数
     Trie(){}
};

Trie root;

void creatTrie(string s)
{
    int len = s.length();
    Trie *p = &root;
    Trie *q;

    for (int i = 0; i < len; ++i) { //对单词s建立字典树
        int id = s[i] - 'a';
        if (p->next[id] == nullptr) {
            q = new Trie();
            for (int j = 0; j < maxn; ++j)
                q->next[j] = nullptr;
            q->v = 1; 
            p->next[id] = q;
        }
        else {
            p->next[id]->v++;
        }

        p = p->next[id];

    }

}

int findTrie(string s) //查找
{
    int len = s.length();
    auto *p = &root; 
    for (int i = 0; i < len; ++i) {
        int id = s[i] - 'a';
        if (p->next[id] == nullptr) return 0;
        p = p->next[id];
    }

    return p->v;
}


int main()
{

    int n,m;
    cin >> n;
    string s;
    for (int i = 0; i < n; ++i) {
        cin >> s;
        creatTrie(s);
    }
    cin >> m;
    for (int i = 0; i < m; ++i) {
        cin >> s;
        int res = findTrie(s);
        cout << res << endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u014046022/article/details/81147663