POJ 2001 : Shortest Prefixes (字典树)

23 篇文章 0 订阅
7 篇文章 0 订阅
题意 : 给你一些字符串,让你为每个字符串找一个最短的前缀,来唯一标识这个字符串,与其他字符串区别开来.这个标志串不能是其他字符串的前缀,除非这个标志串等于这个字符串本身. 考虑用字典树来做.标志当前位是否是结尾位,作为一个边界条件.先将所有字符串按长度排序,每次对一个字符串按位插入字典树里,将路过的位置num加1.最后,如果当前位的num是1,说明到当前位为止的前缀可以唯一标志这个字符串,保存这个前缀. 看提交记录里,好多人都六七百B的代码,而我的代码居然达到了2000B…….果然还是水平不精,实现相同的效果代码还要比人家长,需要多多磨练. ———————————————————————————————————–
总时间限制:
1000ms
内存限制:
65536kB
描述
A prefix of a string is a substring starting at the beginning of the given string. The prefixes of “carbon” are: “c”, “ca”, “car”, “carb”, “carbo”, and “carbon”. Note that the empty string is not considered a prefix in this problem, but every non-empty string is considered to be a prefix of itself. In everyday language, we tend to abbreviate words by prefixes. For example, “carbohydrate” is commonly abbreviated by “carb”. In this problem, given a set of words, you will find for each word the shortest prefix that uniquely identifies the word it represents.

In the sample input below, “carbohydrate” can be abbreviated to “carboh”, but it cannot be abbreviated to “carbo” (or anything shorter) because there are other words in the list that begin with “carbo”.

An exact match will override a prefix match. For example, the prefix “car” matches the given word “car” exactly. Therefore, it is understood without ambiguity that “car” is an abbreviation for “car” , not for “carriage” or any of the other words in the list that begins with “car”.
输入
The input contains at least two, but no more than 1000 lines. Each line contains one word consisting of 1 to 20 lower case letters.
输出
The output contains the same number of lines as the input. Each line of the output contains the word from the corresponding line of the input, followed by one blank space, and the shortest prefix that uniquely (without ambiguity) identifies this word.
样例输入
carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate
样例输出
carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona
来源
Rocky Mountain 2004
/*
 内存: 852kB
 时间: 4ms
 语言: G++
 */
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;

int total, len, flag;
char ini[1010][21], res[1010][21];

struct zifuchuan
{
    int num;
    char str[22];
}s[11000];

struct tree
{
    tree *son[27];
    char val;
    int tail;
    int num;//记录当前这个字母在这个位置出现了多少次
    tree(){
        num = 0;
        for(int i=0;i<27;i++)
        {
            son[i] = NULL;
        }
        tail = 0;
    }
};
bool cmp(zifuchuan a,zifuchuan b)
{
    return strlen(a.str)<strlen(b.str);
}

void insert(tree *&root,char *a,int _index)
{
    if(_index >= len)
        return;
    if(root->son[a[_index]-'a'] == NULL)
    {
        tree *t = new tree;
        t->val = a[_index];
        if(_index == len-1)
            t->tail = 1;
        t->num = 1;
        root->son[a[_index]-'a'] = t;
        insert(root->son[a[_index]-'a'],a,_index+1);
        //cout<<"HHHHHHHHHHHHHHHH        "<<root->son[a[_index]-'0']->val<<endl;
    }
    else
    {
        root->son[a[_index]-'a']->num++;
        insert(root->son[a[_index]-'a'],a,_index+1);
    }
}

int main()
{
    while(scanf("%s",&s[total].str) != EOF)
    {
        s[total].num = total;
        strcpy(ini[total],s[total].str);
        total++;
    }
    //cout<<"???????????"<<endl;
    tree *root = new tree;
    sort(s,s+total,cmp);
    for(int i=0;i<total;i++)
    {
        len = strlen(s[i].str);
        insert(root,s[i].str,0);
    }

    for(int i=0;i<total;i++)
    {
        len = strlen(s[i].str);
        tree *temp = root;
        for(int j=0;j<len;j++)
        {
            temp = temp->son[s[i].str[j]-'a'];
            if(temp->tail == 1)
            {
                temp->num++;
                temp->tail = 0;
                for(int k=0;k<=j;k++)
                    res[s[i].num][k] = s[i].str[k];
                break;
            }
            if(temp->num == 1)
            {
                temp->num++;
                for(int k=0;k<=j;k++)
                    res[s[i].num][k] = s[i].str[k];
                break;
            }

        }
    }

    for(int i=0;i<total;i++)
        printf("%s %s\n",ini[i],res[i]);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值