Light OJ 1129 Trie树 动态建树

做了一道POJ 2001,对TRIE树的思想差不多理解了。其实TRIE树的思想很简单,就是建树,每个节点都有26个子节点(如果是数字的话,那就是10个),然后每个单词从头到尾按照树的深度找下去,最后所有这些单词就挂在TRIE树上啦。


对于TRIE树的操作有:插入、删除、搜索等等。每个操作都很重要,删除如果没有的话在多组数据中就基本上要MLE了,这道题就是这样,一开始我没有做删除操作,MLE了5次。


题意:给你n个数(n <= 10000),问这些数中有没有某个数是另一个数的前缀,比如111和1110。有就输出NO,否则就输出YES。

思路很简单:因为是前缀,因此可以维护TRIE树,维护好之后,再去从TRIE树上找每个数字,如果某个数字已经找到它应该到的结点之后,还能再往下找到其他的数,那就说明满足题目说的条件了,退出判断即可。这种字符串匹配的题目,一开始可能会想到KMP,但是想想如果每个字符都和其他字符去做一遍KMP,那得O(n^2)的复杂度,肯定是要超时的。


顺便吐一个自己的槽,指针没学好真伤不起,malloc和free都用得不溜。敲打


Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
char a[10001][11];
struct node
{
    struct node *next[10];
};

void insert(node *root, const char *tar)
{
    if(root == NULL || *tar == '\0')
        return;
    int id;
    node *p = root;
    while(*tar)
    {
        id = *tar - '0';
        if(p -> next[id] == NULL)
        {
            node *temp = (node *)malloc(sizeof(node));
            for(int i = 0; i < 10; i ++)
                temp -> next[i] = NULL;
            p -> next[id] = temp;
        }
        p = p -> next[id];
        tar ++;
    }
}

bool search(node *root, const char *tar)
{
    int id;
    node *p = root;
    while(*tar && p != NULL)
    {
        id = *tar - '0';
        p = p -> next[id];
        tar ++;
    }
    for(int i = 0; i < 10; i ++)
        if(p -> next[i] != NULL)
            return true;
    return false;
}

void delnode(node *tar)
{
    int i;
    for(int i = 0; i < 10; i ++)
    {
        if(tar -> next[i] != NULL)
            delnode(tar -> next[i]);
    }
    free(tar);
}

int main()
{
    int cse, t = 1;
    scanf("%d", &cse);
    while(cse --)
    {
        node *root = (node *)malloc(sizeof(node));
        for(int i = 0; i < 10; i ++)
            root -> next[i] = NULL;
        scanf("%d", &n);
        for(int i = 0; i < n; i ++)
        {
            scanf("%s", a[i]);
            insert(root, a[i]);
        }
        bool yes = true;
        for(int i = 0; i < n; i ++)
            if(search(root, a[i]))
            {
                yes = false;
                break;
            }
        if(yes)
            printf("Case %d: YES\n", t ++);
        else
            printf("Case %d: NO\n", t ++);
        delnode(root);
    }

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值