您的位置:首页 > 其它

POJ 3630 && HDU 1671 Phone list(静态字典树)

2014-08-01 20:42 447 查看
HDU 1671

POJ 3630

静态字典树,动态会超时

方案一,结构体静态字典树,不排序,在插入时判断

#include <stdio.h>
#define  MAX    10

typedef struct TrieNode
{
int nEndFlag; //标记该字符是否是某一字符串的结尾
struct TrieNode *next[MAX];
}TrieNode;

TrieNode Memory[1000000];
int allocp = 0 , nFlag = 0;

void InitTrieRoot(TrieNode **pRoot)
{
*pRoot = NULL;
}

TrieNode *CreateTrieNode()
{
int i;
TrieNode *p;

p = &Memory[allocp++];
p->nEndFlag = 0;
for(i = 0 ; i < MAX ; i++)
{
p->next[i] = NULL;
}

return p;
}

void InsertTrie(TrieNode **pRoot , char *s)
{
int i , k;
TrieNode *p;

if(!(p = *pRoot))
{
p = *pRoot = CreateTrieNode();
}
i = 0;
while(s[i])
{
k = s[i++] - '0';
if(p->next[k])
{
if(p->next[k]->nEndFlag == 1 || s[i] == '\0') //先短后长 || 先长后短
{
nFlag = 1;
return;
}
}
else
{
p->next[k] = CreateTrieNode();
}
p = p->next[k];
}
p->nEndFlag = 1;  //标记结尾
}

int main(void)
{
int  z , n , i;
char s[11];
TrieNode *Root;

scanf("%d", &z);
while(z-- > 0)
{
nFlag = allocp = 0;
InitTrieRoot(&Root);
scanf("%d" , &n);    getchar();
for(i = 0 ; i < n ; i++)
{
gets(s);
if(!nFlag)    InsertTrie(&Root , s);
}
nFlag ? printf("NO\n") : printf("YES\n");
}

return    0;
}

方案二, 结构体静态字典树,先排序,后插入

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include<cstring>
using namespace std;
#define  MAX    10
int flag = 0;
typedef struct TrieNode
{
int nEndFlag; //标记该字符是否是某一字符串的结尾
TrieNode * next[MAX];
} TrieNode;

TrieNode Memory[1000000];
int allocp = 0 , nFlag = 0;

void InitTrieRoot(TrieNode ** pRoot)
{
*pRoot = NULL;
}

TrieNode * CreateTrieNode()
{
int i;
TrieNode * p;

p = &Memory[allocp++];
p->nEndFlag = 0;

for (i = 0 ; i < MAX ; i++)
{
p->next[i] = NULL;
}

return p;
}

void InsertTrie(TrieNode ** pRoot , char * s)
{
int i , k;
TrieNode * p;

if (!(p = *pRoot))
{
p = *pRoot = CreateTrieNode();
}

i = 0;

while (s[i])
{
k = s[i++] - '0';
if (!(p->next[k]))
{
p->next[k] = CreateTrieNode();
}
p = p->next[k];
if(p->nEndFlag)
{
flag = 1;
return;
}
}
p->nEndFlag = 1;  //标记结尾
}
struct Code
{
int len;
char num[15];
}code[10005];

bool cmp(Code a, Code b)
{
return a.len < b.len;
}
int main()
{
//freopen("1.in","r",stdin);
int  t, n;
TrieNode  *root;
cin >> t;

while (t--)
{
nFlag = allocp = 0;
InitTrieRoot(&root);
int i = 0;
cin >> n;
getchar();

while (n--)
{
gets(code[i].num);
code[i].len = strlen(code[i].num);
i++;
}
sort(code, code + i, cmp);
for (int j = 0; j < i; j++)
{
InsertTrie(&root,code[j].num);
}
if (flag)
{
printf("NO\n");
}
else
{
printf("YES\n");
}

flag = 0;
}
return 0;
}


方案三 , 二维数组的静态字典树,没有指针,一般不会非法内存访问之类的

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int ch[100005][10];
int val[100005];
int sz,flag;
int getid(char ch)
{
return ch-'0';
}
void insert(char *s)
{
int i,pre=0,now;
for(i=0;s[i]!='\0';i++)
{
int id=getid(s[i]);
now=ch[pre][id];
if(!now)
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[pre][id]=sz;
now=sz;
sz++;
}
if(val[now]==1) //此字符串是前面某个字符串的前缀。
{
flag=1;
return;
}
pre=now;
}
val[pre]=1;
for(i=0;i<10;i++)   //前面某个字符串是此字符串的前缀。
if(ch[pre][i])
{
flag=1;
return;
}
}
int main()
{
int T,i,n;
char str[11];
scanf("%d",&T);
while(T--)
{
flag=0;
scanf("%d",&n);
sz=1;
memset(ch[0],0,sizeof(ch[0]));
for(i=0;i<n;i++)
{
scanf("%s",str);
if(!flag) insert(str);
}
if(flag) printf("NO\n");
else printf("YES\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: