【POJ】2001 Shortest Prefixes
题目链接:http://poj.org/problem?id=2001
题目要求求解字符串的最小前缀,最小前缀的意思,举个例子:
abcdef
abcf
ab
那么他们相应的最小前缀:
abcdef abcd
abcf abc
ab ab(因为有字符串包含了ab,那么可以认为ab的最小子串就是他本身)
这是一题没有什么难度的字典树的题目,之所以说没有难度,是因为照着看完题目就知道字典树的模板能够搞定。
唯一的难度是怎么得到最小前缀,关于这个的处理,我的做法如下:
struct node
{
int pos, id; //用id号来存放该字母在整个单词中的序号;
int next[26];
}Tire[MAXN];
那么在已经建立好字典树之后,只需要在search的时候,做如下操作:
int GetPos(char *str, int len)
{
int i, j, cnt=0;
for(i=0; i<len; ++i){
cnt = Tire[cnt].next[str[i]-'a'];
if(Tire[cnt].pos==1) break; //假如该字母在整棵字典树中只出现过一次,即认为到该点为止的字符串不是任何其他单词的子串(显然是自己那个单词的子串… = =)
}
return Tire[cnt].id; //只需返回中断(或者查询结束后最后一个)的字母的id号即可
}
得到返回值之后,对原串需要进行的操作仅仅只是从头开始单个字母输出,一直到返回值位置结束即可。
for(i=0; i<n; ++i){
printf("%s ",pat[i]);
len =strlen(pat[i]);
t = GetPos(pat[i],len);
for(j=0; j<t; ++j) printf("%c",pat[i][j]);
if(i<n-1) printf("\n");
}
建树的过程就是最常规的做法,不过我比较喜欢静态的做法,只是静态的话比较牺牲内存,数组大小的取舍不太好判断(为此,常常runtime error… = = )
void Initial() //初始化头结点很重要,缺少这个语句很有可能wa,提醒再提醒!
{
memset(Tire[0].next,0,sizeof(Tire[0].next));
}
void BuildPos(char *str, int len)
{
int i, j, cnt = 0;
for(i=0; i<len; ++i){
if(Tire[cnt].next[str[i]-'a']==0){
Tire[cnt].next[str[i]-'a'] = ++p; //p是全局变量,初始值为0;
cnt = p;
memset(Tire[cnt].next,0,sizeof(Tire[cnt].next));
Tire[cnt].id = 0;
Tire[cnt].pos = 0 ;
}
else {
cnt = Tire[cnt].next[str[i]-'a'];
}
Tire[cnt].id = i+1; //对id进行的处理
Tire[cnt].pos ++;
}
}
字典树的题目还需要多多练习的,下次希望能学会用动态的做法~
浙公网安备 33010602011771号