【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 ++;   
                  
    }
}

 

字典树的题目还需要多多练习的,下次希望能学会用动态的做法~

posted on 2012-07-30 01:25  Yuna_  阅读(89)  评论(0)    收藏  举报