zoukankan      html  css  js  c++  java
  • 题解 SP4033 【PHONELST

    水一发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;
    }
    
  • 相关阅读:
    js--DOM基本使用
    前端--js基础2
    前端--js基础1
    tcp/udp编程
    关于网络
    异常处理
    装饰器
    1.__new__ 魔术方法 单态(例)模式 __del__ 魔术方法(析构方法) __call__ 魔术方法
    面向对象程序设计及面向对象封装 目录
    script 标签里的 async 和 defer
  • 原文地址:https://www.cnblogs.com/jelly123/p/11221639.html
Copyright © 2011-2022 走看看