zoukankan      html  css  js  c++  java
  • POJ 2001 Shortest Prefixes

    原题传送门

    题目中文翻译:

    Description

    字符串的前缀是从给定字符串的开始处开始的子串。 “carbon”的前缀是:“c”,“ca”,“car”,“carb”,“carbo”和“carbon”。请注意,空字符串在此问题中不被视为前缀,但每个非空字符串都被认为是它自己的前缀。在日常用语中,我们倾向于用前缀缩写词。例如,“carbohydrate”通常缩写为“carb”。在这个问题中,给定一组单词,你会为每个单词找到唯一标识它所代表的单词的最短前缀。

     

    在下面的示例输入中,“carbohydrate”可以缩写为“carboh”,但不能缩写为“carbo”(或更短),因为列表中还有其他词以“carbo”开头。

     

    精确匹配高于前缀匹配。例如,前缀“car”与给定单词“car”完全匹配。因此,毫无疑问地,我们认为“car”是“car”的缩写,而不是“carriage”或列表中以“car”开头的任何其他单词。

    Input

    输入包含至少两行,但不超过1000行。每行包含一个由1到20个小写字母组成的单词。

    Output

    输出包含与输入相同的行数。输出的每一行都包含来自输入相应行的单词,后跟一个空格和唯一且不含歧义的最短前缀标识该单词。

    Sample Input

    carbohydrate

    cart

    carburetor

    caramel

    caribou

    carbonic

    cartilage

    carbon

    carriage

    carton

    car

    carbonate

    Sample Output

    carbohydrate carboh

    cart cart

    carburetor carbu

    caramel cara

    caribou cari

    carbonic carboni

    cartilage carti

    carbon carbon

    carriage carr

    carton carto

    car car

    carbonate carbona

    解题思路:

    一道裸的字典树模板,因为本题需要求每个单词的前缀,所以我们根据每个单词的每一位来建树,这样顶多建21层,空间足够。我们在建树的同时记录每一个前缀(节点)经过次数。

    所以我们要求一个单词的前缀,就从这个单词的头便利到尾,遍历过程中我们会遇到两种情况:

    1.如果便利到了单词尾,说明这个单词的缩写就是这个单词本身

    2.如果便利到一个节点只有一个子节点,则到当前为止的前缀就是单词缩写。(转换为程序语言就是次数为1的节点)

    AC代码:(非指针版本)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 const int N=1e4+5;
     9 char a[N][21];
    10 int n = 1,v[N*30],t[N*30][30],p;
    11 
    12 void query(char o[]) {
    13     int len = strlen(o+1),u = 0;
    14     for(int i = 1;i <= len; i++) {
    15         int c = o[i] - 'a';
    16         if(v[u] == 1) break;
    17         putchar(o[i]);
    18         u = t[u][c];
    19     }
    20     putchar('
    ');
    21 }
    22 
    23 void insert(char o[]) {
    24     int len = strlen(o+1),u = 0;
    25     for(int i = 1;i <= len; i++) {
    26         int c = o[i] - 'a';
    27         if(!t[u][c]) t[u][c] = ++p;
    28         u = t[u][c];
    29         v[u]++;
    30     }
    31 }
    32 
    33 int main() {
    34     while(scanf("%s",a[n++] + 1) != EOF) insert(a[n-1]);
    35     for(int i = 1;i <= n - 1; i++) {
    36         printf("%s ",a[i] + 1);
    37         query(a[i]);
    38     }
    39     return 0;
    40 }
  • 相关阅读:
    linux 命令学习
    反编译学习一:Mac下使用dex2jar
    如何删除你的MacOS上的旧版本Java
    使用screen 遇到的多窗口
    dede简略标题调用标签
    JQ实现导航滚动到指定位置变色,并置顶
    JQ实现当前页面导航加效果(栏目页有效)
    wordpress首页调用指定分类下的文章
    作业1#python用列表实现多用户登录,并有三次机会
    python数据类型之间的转换
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/11146241.html
Copyright © 2011-2022 走看看