poj 2001/1056 Trie树(求单词表的最短前缀/判断立即码)

题意:2001:输入若干单词组成单词表,求每个单词合理的最短前缀(通过前缀确定唯一的单词)。

1056:给定一系列01码,判断是否为立即码,即没有序列为另一个序列的前缀。

思路:使用trie树。其中的flag域用于标定通过这个节点是否有多个单词。初始为0(也就是插入第一个通过该节点的单词时),如果经过此节点有多于一个单词,则置为1。输出方法:从根开始,如果节点flag为1,则继续输出,为0则停止。版本2在trie结构体内进行初始化,运用了C++的写法。(最后是1056的代码)

#include <stdio.h>
#include <string.h>
char s[1005][22];
typedef struct trie{
	int flag;
	struct trie* next[26];
}trie;
trie t[20000];
trie *alloc,*root;
int n=-1;
void init(){
	int i;
	alloc = t;
	root = alloc++;
	root->flag = 0;
	for(i = 0;i<26;i++)
		root->next[i] = NULL;
}
void insert(char s[22]){
	int i,j;
	trie *p,*q;
	p = root;
	for(i = 0;s[i]!='\0';i++){
		if(p->next[s[i]-'a']){//如果该节点已建立(和之前某单词前缀重复),flag置为1
			p = p->next[s[i]-'a'];
			p->flag = 1;
		}else{
			q = alloc++;
			q->flag = 0;
			for(j = 0;j<26;j++)//扫字符串用了i,此地不能再用
				q->next[j] = NULL;
			p->next[s[i]-'a'] = q;
			p = q;
		}
	}
}
void findprefix(char s[22]){
	int i;	
	trie *p = root;
	for(i = 0;s[i]!='\0';i++){
		putchar(s[i]);
		p = p->next[s[i]-'a'];		
		if(p->flag == 0)
			break;
	}
	putchar('\n');
}
int main(){
	int i,j;
	freopen("a.txt","r",stdin);
	init();	
	while(scanf("%s",s[++n])!=EOF)
		insert(s[n]);
	for(i = 0;i<=n;i++){
		printf("%s ",s[i]);
		findprefix(s[i]);
	}
	return 0;
}

poj 2001/1056 Trie树(求单词表的最短前缀/判断立即码)_第1张图片


2001 版本2:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 1040
#define INF 0x3fffffff
using namespace std;
char s[1005][22];
int num = 0;
struct node{
    int flag;
    struct node* next[26];
    node(){
        flag = 0;
        memset(next,NULL,sizeof(next));
    }
}t[20005],*root;
void insert(char x[22]){
    int i;
    struct node *p = root;
    for(i = 0;x[i]!='\0';i++){
        if(!p->next[x[i]-'a']){
            num++;
            p->next[x[i]-'a'] = t+num;
        }else
            p->next[x[i]-'a']->flag = 1;
        p = p->next[x[i]-'a'];
    }
}
void output(char x[22]){
    int i;
    struct node *p = root;
    for(i = 0;x[i]!='\0';i++){
        putchar(x[i]);
        p = p->next[x[i]-'a'];
        if(!p || p->flag == 0)
            break;
    }
    putchar('\n');
}
int main(){
    int i,len = 0;
    root = t;
    while(scanf("%s",s[++len])!=EOF){
        insert(s[len]);
    }
    for(i = 1;i<=len;i++){
        printf("%s ",s[i]);
        output(s[i]);
    }
    return 0;
}


1056:

#include <stdio.h>
#include <string.h>
typedef struct node{
	int flag;
	struct node *next[2];
}Node;
Node tree[100000],*root,*alloc;
char s[1025];
int c = 1,flag;
void init(){
	flag = 1;
	alloc = tree;
	root = alloc++;
	root->flag = 0;
	root->next[0] = root->next[1] = NULL;
}
int insert(char *s){
	int i,flag = 1;
	Node *p,*q;
	p = root;
	for(i = 0;s[i]!='\0';i++){
		if(!p->next[s[i]-'0']){
			flag = 0;
			q = alloc++;
			q->flag = 0;
			q->next[0] = q->next[1] = NULL;
			p->next[s[i]-'0'] = q;
		}
		p = p->next[s[i]-'0'];
		if(p->flag)
			return 0;
	}
	p->flag = 1;
	return flag==0;
}
int main(){
	//freopen("a.txt","r",stdin);
	while(scanf("%s",s)!=EOF){
		int j;
		init();
		do{
			if(flag){
				j = insert(s);
				if(!j)
					flag = 0;
			}
			scanf("%s",s);
		}while(strcmp(s,"9"));
		if(flag)
			printf("Set %d is immediately decodable\n",c++);
		else
			printf("Set %d is not immediately decodable\n",c++);
	}
}


你可能感兴趣的:(poj 2001/1056 Trie树(求单词表的最短前缀/判断立即码))