给你一些名字,让你用一台打印机去打印这些名字,打印机只有三个操作
(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; }