【HihoCoder】Trie树 (字符串匹配)

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。

这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题:Ho,你能不能对于每一个我给出的字符串,都在这个词典里面找到以这个字符串开头的所有单词呢?

输入

输入的第一行为一个正整数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给出的字符串为前缀的单词的个数。

样例输入

5

babaab

babbbaaaa

abba

aaaaabaa

babaababb

5

babb

baabaaa

bab

bb

bbabbaab

样例输出

1

0

3

0

0

 

 

首先给出trie树的原理:trie树是以空间换取时间,利用字符串的公共前缀来降低查询开销。举个例子:add,addition,这两个单词,他们的公共前缀是add,应用trie数进行存储的时候,add只会被存储一次,如果以add为前缀的单词很多,这样就节省了很多的存储空间。

trie树的性质:

1,字符种数决定trie中branch的个数,以单词为例,共有26个英文单词,那么每个节点中会有26个指针域。

2,branch数组的下标代表字符相对于a的相对位置。

3,插入和查询的时间复杂度均与给定单词的长度len成正比,即为:o(len)。

4,每个节点附设一个count域,若count域被初始化为0,如果在插入所有单词之后,遍历trie树的时候,count不等于0,则表示从根节点到此节点的

每个字母连接成的单词出现的次数。

如图所示,该trie树存有abc、d、da、dda四个字符串,如果是字符串会在节点的尾部进行标记(count!=0)。没有后续字符的branch分支指向NULL:

 《【HihoCoder】Trie树 (字符串匹配)》

代码:

#include <iostream>
#include <string.h>
using namespace std;
 
#define MaxNum 26
 
typedef struct sTrieNode
{
    int count;
    bool IsWord;
    struct sTrieNode* next[MaxNum];
}TrieNode;
 
TrieNode* CreateTrieNode()
{
    TrieNode*NewTrie=new TrieNode;
    NewTrie->count=0;
    NewTrie->IsWord=false;
    memset(NewTrie->next, NULL , sizeof(NewTrie->next));
    return NewTrie;
}
 
void InsertWord(TrieNode* root,char* word)
{
    TrieNode *Node=root;
    int Index;
    char *str=word;
    while (*str!='\0')
    {
        Index=*str-'a';
        if (Node->next[Index]==NULL)
        {
            Node->next[Index]=CreateTrieNode();
        }
        Node=Node->next[Index];
        Node->count++;
        str++;
    }
    Node->IsWord=true;
}
 
int FindWord(TrieNode* root, char* word) 
{ 
    TrieNode*Node = root; 
    char *str = word; 
    int Index; 
    while( *str!='\0') 
    { 
        Index =*str - 'a'; 
        Node =Node->next[Index];   
        if(Node == NULL) 
            return 0; 
        str++;
    } 
    return Node->count; 
}
 
int main()
{
    TrieNode*Root=CreateTrieNode();
    char word[10];
    int num;
    cin>>num;
    while (num--)
    {
        cin>>word;
        InsertWord(Root,word);
    }
    cin>>num;
    while (num--)
    {
        cin>>word;
        cout<<FindWord(Root,word)<<endl;
    }
    return 0;
}

 

    原文作者:Trie树
    原文地址: https://blog.csdn.net/sea_mo/article/details/37913597
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞