题解 SP4033 【PHONELST - Phone List】

水一发trie板子~

先说这个题怎么套上板子
首先我们判断是否有前缀可以边插入边判断
当我们经过了一个完整的字符串(即当前节点到了一个有标记的节点上)
就是有前缀
我们当然也可以无脑先判断一发(比如我这个)
然后无脑插入就是
减少了一定的编程难度


然后我丧心病狂异想天开写了一发动态的trie
指针警告
好处是内存省下来了
当然删除的时间上来说是省不下来了
具体看代码(代码向预警

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

using namespace std;
//字典集合大小 
const int Z=10;
struct trie{
    //Z个子节点 
    trie *ch[Z];
    //是否存在字符串的标记挂载 
    bool vst;
}rt,*root=&rt;//根节点 
//输入用的字符串 
string input;

void insert(string str)
{
    if (str.size()<1)return ;//空字符串返回 
    trie *now=root;//从根节点开始向下插入 
    for (register int i=0;i<str.size();i++)
    {
        int num=str[i]-'0';//子节点下标 
        if (now->ch[num]==NULL)//需要开一个新的节点 
        {
            now->ch[num]=new trie();//纳新 
            //初始化节点(也可以写到构造函数里 
            for (register int j=0;j<Z;j++)
            {
                now->ch[num]->ch[j]=NULL;//设置成空 
                now->ch[num]->vst=false;//设置不存在当前子节点表示的字符串 
            }
            now=now->ch[num];//向下一个节点移动 
        }
        else now=now->ch[num];//向下一个节点移动 
    }
    now->vst=true;//挂载当前字符串 
}

bool find(string str)
{
    if (str.size()<1)return true;//空字符串走人 
    trie *now=root;//从根节点开始 
    for (register int i=0;i<str.size();i++)
    {
        int num=str[i]-'0';//下标 
        //如果存在没有插入的节点,而且没有经过任何一个完整的字符串,
        //一定是不存在任何一个字符串与其为前缀关系 
        if (now->ch[num]==NULL)return false;
        else
        {
            //经过一个完整的字符串,即经过的这个字符串
            //是str的前缀 
            if (now->ch[num]->vst)return true;
            now=now->ch[num];//向下一个节点移动 
        }
    }
    //存在另一个字符串包含这个字符串
    //即有另一个字符串使得这个字符串是其前缀 
    return true;
}
//无脑删除,回收空间 
void dfs(trie *now)
{
    for (register int i=0;i<10;i++)
    {
        if (now->ch[i]!=NULL)
            dfs(now->ch[i]);
    }
    if (now!=root)delete now; 
}
//重新建树 
void build()
{
    dfs(root);
    for (register int i=0;i<10;i++)
    {
        root->ch[i]=NULL;
    }
    root->vst=false;
}

int main()
{
    int T,n;
    cin>>T;
    while (T--)
    {
        bool flag=false;
        //先重新建空树 
        build();
        cin>>n;
        while (n--)
        {
            cin>>input;
            //只要是存在前缀关系就行 
            flag=find(input)||flag;
            insert(input);
        }
        //存在即NO 
        puts(flag?"NO":"YES");
    }
    return 0;
}

转载于:https://www.cnblogs.com/jelly123/p/11221639.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值