poj 2001 Shortest Prefixes trie入门
题意:输入不超过1000个字符串,每个字符串为小写字母,长度不超过20;之后输出每个字符串可以简写的最短前缀串;
Sample Input
carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate
Sample Output
carbohydrate carboh (carbo不止一个字符串含有,所以不能作为简写符号) cart cart carburetor carbu caramel cara caribou cari carbonic carboni cartilage carti carbon carbon carriage carr carton carto car car carbonate carbona
对于trie的理解主要是对空间复杂度的理解;这道题直接使用了26叉trie树,maxnode并不是字符串的个数,而是字符串个数乘以长度,每一个节点还含有26个子节点。其实存储的很稀疏;
在insert中,从根节点开始顺序查找是否有第i个字符的子节点,没有直接重新开一个行向量(++sz),这就导致了最坏的时间复杂度为maxn * maxl * 26;只是方便查找;查找时直接在线输出即可;
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> #include<map> #include<queue> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 typedef pair<int,int> PII; #define A first #define B second #define MK make_pair typedef __int64 ll; template<typename T> void read1(T &m) { T x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m = x*f; } template<typename T> void read2(T &a,T &b){read1(a);read1(b);} template<typename T> void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } const int maxl = 1000 * 20 + 10; struct Trie{ int ch[maxl][26]; int val[maxl]; int sz; Trie(){sz = 1;MS0(ch);MS0(val);} void Insert(char *s){ int u = 0, n = strlen(s); for(int i = 0;i < n;i++){ int c = s[i] - 'a'; if(!ch[u][c]){ //MS0(ch[u]); //* 开始建trie时,初始化了,这里不能删除加入的信息 ch[u][c] = sz++; } u = ch[u][c]; val[u]++; } } int Find(char *s){ int u = 0, n = strlen(s); for(int i = 0;i < n;i++){ int c = s[i] - 'a'; putchar(s[i]); u = ch[u][c]; if(val[u] == 1) break; } } }trie; char s[1001][22]; int main() { int n = 0; while(scanf("%s",s[n]) == 1){ trie.Insert(s[n++]); } rep0(i,0,n){ printf("%s ",s[i]); trie.Find(s[i]); puts(""); } return 0; }