POJ 2001 Shortest Prefixes (字典树)

题目类型  字典树

题目意思
给出最多 1000 个最长 20 的字符串 问每个字符串可以准确识别的最短识别长度对应的字符串是什么
准确识别长度的意思是如果前这个长度的字符都匹配的话那么就肯定是这个字符串了(即没有其他字符串符合这个要求 除非那个字符串就只由这么多字符组成)

解题方法
字典树 
记录每个结点被遍历的次数 查询的时候当某个结点遍历次数为 1 即说明到这个结点为止已经可以识别了 如果一直都没碰到这样的结点说明整个字符本身是那个要求输出的字符串

参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define B printf("BUG\n");
const int maxnode = 20100 + 10;
const int sigma_size = 27;

char str[1010][sigma_size];

struct Trie {
	int ch[maxnode][sigma_size];
	int val[maxnode];
	int sz;
	Trie () { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
	int idx(char c) { return c - 'a'; }

	void insert(char * s) {
		int u = 0, n = strlen(s);
		for( int i=0; i<n; i++ ) {
			int c = idx(s[i]);
			if(!ch[u][c]) {
				memset(ch[sz], 0, sizeof(ch[sz]));
				val[sz] = 0;
				ch[u][c] = sz++;
			}
			u = ch[u][c];
			val[u]++;
		}
	}

	int query(char * s) {
		int u = 0, n = strlen(s);
		for( int i=0; i<n; i++ ) {
			int c = idx(s[i]);
			u = ch[u][c];
			if(val[u] <= 1) return i+1;
		}
		return n;
	}
};

Trie t;
int main() {
	freopen("in", "r", stdin);
	int k = 0;
	while(cin.getline(str[k],30)) {
		t.insert(str[k]);
		k++;
	}
	for( int i=0; i<k; i++ ) {
		int len = t.query(str[i]);
		printf("%s ", str[i]);
		for( int j=0; j<len; j++ ) printf("%c", str[i][j]);
		printf("\n");
	}
	return 0;
}

你可能感兴趣的:(字典树)