Hdu1251 统计难题

今天是我第一次接触树,学习树;碰到了这个问题;结果上网看了看别人的代码,发现解法多样,这篇文章不是写AC代码的(虽然代码都能AC)而是写我对这不同解法的理解与感悟;以及第一天学习下来的成果。 ---Keep Codeing---

Hdu1251 统计难题

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=69422#problem/E

解法一:建立一颗树,因为这里有26个字符,因此建立字母树

#include <iostream>
#include <cstdio>
#include <cstring>
//char *str;
char *question[100];

struct Node
{
    int num; //记录当前结点的子树个数;
    Node *child[26]; //最多有26个子树;下标可以保存当前的字符 ch-'a'
}*root;


void BuiltTree(char *s) //增加一个字串
{
    Node *t, *p;    //目标指针
    p = root;           //目标指针指向根节点
    int n = strlen(s);
    int i;
    for(i = 0; i < n;i++)
    {
        if(p->child[s[i]-'a'] == NULL) //如果该节点没有这个子结点
        {
            t = new Node;   //,申请内存空间
            t->num = 1;     //并将这个子结点的num变为1(表示自己一个子树);
            for(int j = 0; j < 26;j++) //将这个新的子节点的子节点变为空(因为它本身也是新增的,所以子节点必为空)
            {
                t->child[j] = NULL;
            }
            p->child[s[i]-'a'] = t;  //关键的一步,将对象结点的子节点保存该子结点的子结点;
        }
        else  p->child[s[i]-'a']->num++; //有该结点就将该结点num + 1;(表示新增了一个子树);

        p = p->child[s[i]-'a']; //目标指针指向下一个结点

    }
}

void InitRoot()//初始化根结点
{
    root = new Node;    //为根结点申请空间
    root->num = 0;      //计数为 0(不属于字符串的一部分)
    for(int i = 0; i < 26;i++)
    {
        root->child[i] = NULL;
    }
}

int SearchTree(char *s)
{
    Node *p; //目标指针
    int n = strlen(s);
    p = root;
    for(int i = 0; i < n;i++)
    {
        if(p->child[s[i]-'a'] == NULL) //循环还没结束 ,到某个字符找不到了,证明没有满足前缀所有字符的字符串,因此返回0;
        {
            return 0;
        }
        p = p->child[s[i]-'a']; //如果上一个字符满足前缀,则指向下一个字符;
    }
    return p->num; // 循环结束前没有返回证明至少找到前缀满足的字符串,只要输出该结点的num的值即可
}

int main()
{
    char str[15];
    InitRoot();
    while(1)
    {
        gets(str);
        if(strcmp(str,"") == 0)
            break;
        BuiltTree(str);
    }
    while(~scanf("%s",str))
    {
        printf("%d\n",SearchTree(str));
    }
    return 0;
}

</cstring></cstdio></iostream>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值