hihoCoder1107 Shortest Proper Prefix Tire树

题目链接:hihoCoder1107


题目大意:给你n个字符串,定义proper prefix为其中某个字符串s的前缀满足:在这n个字符串中出现的次数不超过5次;定义shortest proper prefix为其中某个字符串s满足:s是proper prefix且s的所有前缀(不包括s本身)都不是proper prefix.现在让找出这n个字符串中shortest proper prefix的个数。



分析:以这n个字符串建立一颗字典树,从根节点开始往下遍历,如果满足当前节点的num值不大于5且不为0(不为0保证了该前缀出现过),那么计数器加1,同时不再往下遍历,改而遍历该节点的兄弟节点,知道遍历所以的节点为止。


实现代码如下:

#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
#define son_num 30 //字符串中包含的字符个数
#define maxn 2000010 //单词的最大长度
struct tire
{
    int num; //纪录到达该节点的字符串的个数,即相同前缀数
    struct tire *next[son_num]; //纪录下一个节点
};
tire *root;
char str0[maxn];
int ans;

tire *init() //创建新节点
{
    tire *p=(tire *)malloc(sizeof(tire));
    for(int i=0;i<son_num;i++)
      p->next[i]=NULL;
    p->num=0;
    return p;
}

void insert(tire *root,char str[]) //插入操作
{
    int i=0;
    tire *p=root;
    while(str[i]!='\0')
    {
        if(!p->next[ str[i]-'a' ]) //如果不存在,建立新节点
          p->next[ str[i]-'a' ]=init();
        p=p->next[ str[i]-'a' ];
        p->num++;
        i++;
    }
}

void solve(tire *node)
{
    tire *p=node;
    if(p->num<=5&&p->num!=0)
    {
        ans++;
        return ;
    }
    for(int i=0;i<son_num;i++)
      if(p->next[i]) solve(p->next[i]);
}

void del(tire *root) //清空操作
{
    for(int i=0;i<son_num;i++)
      if(root->next[i]!=NULL)
        del(root->next[i]);
    free(root);
}

int main()
{
    root=init();  //创建根结点
    int n; //n为建立字典树的单词数
    cin>>n;
    ans=0;
    for(int i=0;i<n;i++) //建立字典树
    {
        scanf("%s",str0);
        insert(root,str0);
    }
    solve(root);
    printf("%d\n",ans);
    del(root); //释放字典树占用的空间
    return 0;
}


你可能感兴趣的:(hihoCoder1107 Shortest Proper Prefix Tire树)