poj 3630 Phone List (trie~)

来源:互联网 发布:手机像素图软件 编辑:程序博客网 时间:2024/05/22 08:06

题意:判断是否有序列是另一序列的前缀。


算法:

1、可以先把序列按长度排序,然后用TRIE找前面序列是否是后面序列的前缀。

2、如果不排序,则既要判断前面是否是后面的前缀,又要判断后面是否是前面的前缀。

分别是   由于序列末尾的v=1,则第一种情况一定会中途遍历到v=1的节点。

               后一种情况一定是  当前序列已经到了末尾,而它的next[i]至少有一个不为空。

               另外若两个序列相等,就是即将要标记为v=1的节点已经是1。


malloc申请空间的trie超时了。。。。

只能改为静态数组。


#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>using namespace std;struct node{    int v;    node* next[10];}trie[1000000];int c,flag;void init(node* &rt){    rt = &trie[c++];    memset(trie,0,sizeof(trie));    rt->v = 0;}void insert(char s[],node *rt){    int len = strlen(s);    node *t;    for(int i=0;i<len;i++)    {        int id = s[i]-'0';        if(rt->next[id]==NULL)        {            t = &trie[c++];            t->v = 0;            rt->next[id] = t;        }        if(rt->next[id]->v==1) //如果之前有一个短序列是它的前缀        {            flag = 1;            return;        }        rt = rt->next[id];    }    for(int i=0;i<10;i++)  //如果当前序列为之前一个长序列的前缀    {        if(rt->next[i]!=NULL)        {            flag = 1;            return;        }    }    if(rt->v==1)  //如果当前序列和之前的序列相等        flag = 1;    else rt->v = 1;}int main(){    int T,n;    char s[15];    node *rt;    scanf("%d",&T);    while(T--)    {        c = 0,flag = 0;        init(rt);        scanf("%d",&n);        for(int i=0;i<n;i++)        {            scanf("%s",s);            if(!flag)                insert(s,rt);        }        if(flag)            puts("NO");        else puts("YES");    }    return 0;}




0 0
原创粉丝点击