POJ 3630 Phone List 静态字典树Trietree

学习了一下静态字典树,特地来写一发试试模板。


第一眼看到静态字典树和链式前项星好像,感觉差不多的思想(链式数组)

链式前项星edge[]数组中存的是一条条边,对于每条边在next中存的是与

这条边同起点的下一条边所在下标。这些同起点的边就组成了一个链表,

只不过这个链表存在数组中,(该数组叫做链式数组),head[]数组存的就是

表头。对每个顶点i可以通过head[i]知道表头,进而找出所有同起点边。


静态字典树和链式前项星一样,先开一个足够大的数组,只不过链式前项星中

存的是一条条边,而静态字典树中存的是一个个点(通俗理解就是字符)。

Trie结构体中有一个next[]数组,这个数组是字符的索引,next数组存的是下一个
字符在trie[]数组中的位置(是不是和链式前项星很像~逃),存入字典树的
一个string的每个字符就组成了一个链表,链表头是trie[0]。



POJ 3630 题目大意:

给你n个电话号码,如果其中有一个电话号码是另一个电话号码的前缀,则输出NO

否则输出YES。如:

12344

123

输出NO

123

12344

输出NO

1234

7657

输出YES




#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<cstring>
#include<queue>
#include<stack>
#include<list>

using namespace std;

typedef long long ll;
const int maxn=100000;
const ll INF=1e9;
const ll mod=1e9+7;


struct Trie{
    int next[26];
    int num;
    bool isStr;
    void init(){
        num=0;
        isStr=false;
        memset(next,0,sizeof(next));
    }
}trie[maxn];

int cnt;

void init(){
    cnt=0;
    for(int i=0;i<maxn;i++){
        trie[i].init();
    }
}


void Insert(char *s){
    int pre=0;
    for(int i=0;s[i];i++){
        int id= s[i]-'0';
        if(trie[pre].next[id]==0){
            trie[pre].next[id]=++cnt;
            pre=cnt;
            /*
            *
            */
            trie[pre].num++;

        }
        else{
            pre=trie[pre].next[id];
            /*
            *
            */
            trie[pre].num++;

        }
    }
    trie[pre].isStr=true;

}


bool Find(char *s){
    int pre=0;
    bool ok=false;
    for(int i=0;s[i];i++){
        int id=s[i]-'0';
        if(trie[pre].next[id]==0){
            return ok;
        }
        pre=trie[pre].next[id];
        if(trie[pre].isStr)ok=true;
    }
    if(pre)ok=true;
    return ok;//trie[pre].num;
}


int main()
{
	//freopen("A-large.in","r",stdin);
    	//freopen("A-large.out","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        init();
        char s[30];
        int flag=1;
        for(int i=0;i<n;i++){
            scanf("%s",s);
            if( Find(s) )flag=0;
            Insert(s);
        }
        if(flag)puts("YES");
        else puts("NO");
    }

	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值