zoukankan      html  css  js  c++  java
  • hdu3460 字典树(打印机)

    题意:
           给你一些名字,让你用一台打印机去打印这些名字,打印机只有三个操作
    (1)打印的都是小写字母
    (2)每次可以在当前字母的后面加一位,或删除一位。
    (3)打印当前串
    问你最少多少步可以吧所有的名字都打完。

    思路:
          这个题目首先要看懂题目,不然测试数据都模拟不过去,曾加一个字母,删除一个字母,打印,每一种都算是一步,首先我们把所有的字母都建在一棵树里,也就是字典树存下所有的名字,ans =(字典树节点数-1)* 2 + 名字数 - 最长的名字     
    下面分步理解这个式子,节点数-1是因为字典树的根节点没有字母,*2是因为假设每一个字母增加上去又删除了,+名字数 是因为每个名字都要输出一下,输出算一步,-最长名字长度,是因为最后一个名字是不用再打印机上删除的,我们选择一个最每一长的这样能达到步骤最少。然后在整体理解下,在一棵树上,每一个节点都是一棵子树的树根,对于每一棵树,他的根节点的字母只要被增加一次删除一次就行了(最后的不用删除)。这样就可以很好的理解答案为什么是

    ans = T_n * 2 + n - maxl 了。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    typedef struct Tree
    {
        Tree *next[26];
    }Tree;
    
    Tree root;
    int sum;
    
    void Buid_Tree(char *str)
    {
        int len = strlen(str);
        Tree *p = &root ,*q;
        for(int i = 0 ;i < len ;i ++)
        {
            int id = str[i] - 'a';
            if(p -> next[id] == NULL)
            {
                sum ++;
                q = (Tree *)malloc(sizeof(root));
                for(int j = 0 ;j < 26 ;j ++)
                q -> next[j] = NULL;
                p -> next[id] = q;
            }
            p = p -> next[id];
         }
    }
    
    int main ()
    {
        int n ,i;
        char str[55];
        while(~scanf("%d" ,&n))
        {
           for(sum = 0 ,i = 0 ;i < 26 ;i ++)
           root.next[i] = NULL;
           int maxl = 0;
           for(i = 1 ;i <= n ;i ++)
           {
              scanf("%s" ,str);
              if(maxl < strlen(str)) maxl = strlen(str);
              Buid_Tree(str);
           }
           printf("%d
    " ,sum * 2 + n - maxl);
         }
         return 0;
    }
    

  • 相关阅读:
    《数据库系统概论》第三章笔记
    《数据库系统概论》第二章笔记
    《数据库系统概论》第一章笔记
    《Java并发编程的艺术》第九章笔记
    Dijkstra算法
    LaTex插图总结
    PDF中点击参考文献如何回到正文
    清华大学SCI论文写作心得
    LaTex写论文
    MATLAB中ode23函数,龙格库塔函数
  • 原文地址:https://www.cnblogs.com/csnd/p/12062977.html
Copyright © 2011-2022 走看看