HDU - 1251 统计难题(字典树)

点我看题

题意:就是题目的字面意思,求以某字符串为前缀的单词个数.

分析:字典树的基础题.本题字典树的结点加了exist元素会爆内存的,本来字典树就是牺牲空间换时间.

点我了解字典树(具体的还得自己动手才能掌握哇)

参考代码:

/*字典树 求前缀问题*/
#include
#include
#include
#include
#include
#include
#include

using namespace std;
//#define mem(a,b) memset(a,b,sizeof(a))
typedef struct TrieNode{
    int count;//统计单词前缀出现的次数
    struct TrieNode *child[26];//指向各子树的指针
//    bool exist;//标记该结点处是否构成单词(本题加了这个会爆内存啊啊啊)
}*Trie;

TrieNode* CreateTrieNode()
{
    TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode));
    node->count = 0;
//    node->exist = false;
    memset(node->child,0,sizeof(node->child));
    return node;
}
Trie root = CreateTrieNode();//初始化字典树的根节点

void TrieInsert( char str[])
{
    Trie node = root;
    int p = 0;//str的下标
    int id;
    while( str[p] != '\n')
    {
        id = str[p]-'a';
        if( node->child[id] == NULL)
            node->child[id] = CreateTrieNode();
        node = node->child[id];
        p++;
        node->count += 1;
    }
//    node->exist = true;
}

int TrieSearch( char str[])
{
    Trie node = root;
    int p = 0;//str的下标
    int id;
    while( str[p] != '\n')
    {
        id = str[p]-'a';
        node = node->child[id];
        p++;
        if( node == NULL)
            return 0;
    }
    return node->count;
}

int main()
{
    char str[12];
    while( fgets(str,12,stdin) && strcmp(str,"\n"))//用的是ubuntu17.04 gets用不了,所以用了fgets
        TrieInsert(str);

    while( fgets(str,12,stdin))
        printf("%d\n",TrieSearch(str));
    return 0;
}


补充:一般用指针建树比较容易出错,嗯然后今天写了个数组实现字典树的,一个很**的问题出现了,之前说过我的电脑gets读取字符串编译过不了,今天混用fgets和scanf读取字符串,结果一直re==,都统一换成fgets就好了

/*字典树*/
/*数组实现*/
#include
#include
#include
#include
#include


using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e6+10;
int TrieTree[maxn][26];//数组表示字典树
int cnt[maxn];//每个结点的前缀个数
int node;//所有结点个数


//根结点初始化
void init()
{
    mem(TrieTree[0],0);
    cnt[0] = 0;
    node = 1;
}


void TireInsert( char word[])
{
    int p = 0;//单词的下标
    int root = 0;//word往下走的子树的根结点
    while( word[p] != '\n')//fgets读取字符串时,后面的\n也被读入
    {
        int id = word[p]-'a';//用数字代替单词
        if( TrieTree[root][id] == 0)//当前根结点的子树没有出现以id为根子树
        {
            //TrieTree
            mem(TrieTree[node],0);
            cnt[node] = 0;
            TrieTree[root][id] = node++;//他是第多少个结点
        }
        cnt[TrieTree[root][id]]++;
        root = TrieTree[root][id];
        p++;
    }
}


int TireSearch( char word[])
{
    int p = 0;//word的下标
    int root = 0;
    int pos = 0;
    while( word[p] != '\n')
    {
        int id = word[p]-'a';
        if( TrieTree[root][id] == 0)
            return 0;
        else
            pos = TrieTree[root][id];
        root = TrieTree[root][id];
        p++;
    }
    return cnt[pos];
}


int main()
{
    char word[13];
    init();
    while( fgets(word,13,stdin) && strcmp(word,"\n"))
        TireInsert(word);


    while( fgets(word,13,stdin))
        printf("%d\n",TireSearch(word));


    return 0;
}


你可能感兴趣的:(数据结构--字典树)