POJ 2001 解题报告 trie 树

题目意思:

就是找能标识每个字符串自身的最短前缀。可以用 Trie 树解决,只需要记录每个结点的访问次数,那么每个字符串的最短前缀,要么就是到访问次数为1的那个字符结点为止的字符串,要么就是遍历完毕还没有遇到访问量为1的字符结点时,最短前缀就是自身。


代码:POJ 2001

#include <cstring>
#include <cstdio>

#define maxn 1010

typedef struct node {
	int cnt;
	int childs[26];
	void init() {
		cnt = 1;
		memset(childs, -1, sizeof(childs));
	}
} Node;

Node ns[maxn * 100];
char input[maxn][100];
int root;
int node_num;

int create()
{
	node_num = 0;
	ns[node_num].init();
	return node_num;
}

void insert(int root, char *s)
{
	if (*s == '\0') return;
	int index = *s - 'a';
	int child = ns[root].childs[index];
	if (child != -1) {
		ns[child].cnt++;
		insert(child, s+1);
		return;
	}
	else {
		node_num++;
		ns[node_num].init();
		
		ns[root].childs[index] = node_num;
		insert(node_num, s+1);
		return;
	}
}

void query(int root, char *s)
{//如果某个字符所在的结点 cnt 值是1,那到这个字符为止的都是最短前缀。
 //或者该字符串遍历完毕也找不到 cnt 为1的,那整个字符串都是最短前缀。
 //具体画图则可以观察到。
	printf("%s ", s);
	char *p = s;
	int index = *s++ - 'a';
	int child = ns[root].childs[index];
	while (*s != '\0' && ns[child].cnt != 1) {
		index = *s++ - 'a';
		child = ns[child].childs[index];
	}
	*s = '\0';
	printf("%s\n", p);
}

int main()
{
	//freopen("testdata/2001.txt", "r", stdin);
	root = create();
	int num = 0 ;
	while (scanf("%s", &input[num][0]) != EOF) insert(root, &input[num++][0]);
	for (int i = 0; i < num; ++i) query(root, &input[i][0]);
	
	return 0;
}


你可能感兴趣的:(tree,ACM,poj,trie)