hdu 3460 Ancient Printer

点击打开链接hdu3640

思路:字典树

分析:
1 题目要求的是给定n个字符串,现在有一台的打印机有三种操作“取字符”,“删除最后一个字符”,“打印当前单词”,问最少需要几次的操作(最后一个单词不用删除)。
2 要最少的次数,那么就是使得最后一个单词必须是所有单词中的最长的,所以这里需要涉及到对二维数组的排序利用qsort从小到大;
3 如果两个单词有相同的公共前缀那么肯定是可以减少输入的次数,所以在建字典树的时候应该在节点里面用一个flag标记当前的字符是否被取过,还有要几下以当前的单词为前缀的字符串的个数count。
4 几下了以当前字符串为前缀的字符串的个数的时候,那么我们在具体查找的时候就是判断当前的字符是否被取过,如果没被取过那么标记为取过并ans++;每一次都要把当前字符的count--,当count = 0并且不是最后一个单词的时候就要开始删除所以这个时候ans++;

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define MAXN 1000010
#define MAX 60
#define N 30

int cnt , n;
int ans;
char words[10010][MAX];
struct Trie{
   int count;
   bool flag;
   Trie *child[N];
}trie[MAXN];
Trie *root;

/*自定义的函数*/
int cmp(const void *str1 , const void *str2){
    return strlen((char*)str1) - strlen((char*)str2);
}

/*字典树的空间的分配*/
Trie* newTrie(){
   trie[cnt].count = 0;
   trie[cnt].flag = false;
   for(int i = 0 ; i < N ; i ++)
     trie[cnt].child[i] = NULL;
   return &trie[cnt++];
}

/*字典树的插入*/
void insert(char *str){
    Trie *s = root;
    int len = strlen(str);
    for(int i = 0 ; i < len ; i++){
       int num = str[i]-'a';
       if(s->child[num] == NULL)
         s->child[num] = newTrie();
       s = s->child[num];
       s->count++;/*这里自增加1*/
    }
}

/*字典树的查找*/
void search(char *str , int j){
    Trie *s = root;
    int len = strlen(str);
    for(int i = 0 ; i < len ; i++){
       int num = str[i]-'a';
       s = s->child[num];
       if(s->flag == false){
         ans++;
         s->flag = true;
       }
       s->count--;/*这个地方一定要减1,不然就是WA*/
       if(s->count == 0 && j != n-1)
         ans++;
    }
    ans++;/*每一个单词都要打印就是加1*/
}

int main(){
   while(scanf("%d" , &n) != EOF){
       cnt = 0;
       root = newTrie();
       for(int i = 0 ; i < n ; i++){
          scanf("%s" , words[i]);
          insert(words[i]);
       }
       qsort(words , n , sizeof(words[0]) , cmp);/*按照长度排序*/
       ans = 0;
       for(int i = 0 ; i < n ; i++)
          search(words[i] , i);
       printf("%d\n" , ans);
   }
   return 0;
}
时间: 2024-12-01 06:51:17

hdu 3460 Ancient Printer的相关文章

算法题:HDU 3460 Ancient Printer

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3460 题目: Ancient Printer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 955    Accepted Submission (s): 441 Problem Description The contest is be

【DP专辑】ACM动态规划总结

转载请注明出处,谢谢.   http://blog.csdn.net/cc_again?viewmode=list          ----------  Accagain  2014年5月15日 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力.建模抽象能力.灵活度. 本人动态规划博客地址:http://blog.csdn.net/cc_again/article/category/1261899 ******************

HDU 4081 Qin Shi Huang&#039;s National Road System (次小生成树算法)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=4081 题目: Problem Description During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---- they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the

hdu 1010 Tempter of the Bone

hdu 1010 的传送门 The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately

hdu 1527

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1527 hint:威佐夫博弈 基本类似于模板 #include <iostream> #include <cmath> #include <cstdio> using namespace std; const double q = (1 + sqrt(5.0)) / 2.0; // 黄金分割数 int Wythoff(int a, int b) { if (a > b)

hdu 2551 竹青遍野

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2551 hint:就是读懂题就行了 #include <iostream> #include <cstdio> using namespace std; typedef long long LL; LL data[1005]; int main() { data[0]=0; for(int i=1; i<1005; i++) data[i]+=data[i-1]+i*i*i; LL

hdu 2054 A == B?

http://acm.hdu.edu.cn/showproblem.php?pid=2054 此题巨坑,刚开始我以为是简单的水题,就用strcmp过, but错了,后来经过我苦思冥想,结果还有几组数据 0.0 和 0,1.000和1.0 , 但是我不太确定前面的0是不是有作用我还是写了,但是有人过的时候,前面的0没考虑比如: 002和2可能是相等的,也可能是不想等的所以不用判断,只能说明hdu数据不是很强啊,嘿嘿 代码如下: #include <iostream> #include <c

hdu 4430 Yukari&#039;s Birthday

点击打开链接hdu 4430 思路:枚举r+二分k 分析: 1 题目要求的是找到一组最小的r*k,如果r*k相同那么就找r最小的. 2 很明显k>=2,根据n <= 10^12,那么可以知道r的最大值r<50,所以只要枚举枚举r的值,然后二分k的大小找到所有的解,存入一个结构体里面,然后在对结构体排序,那么这样就可以得到最后的ans 3 注意题目说了中心点最多一个蜡烛,所以写二分的时候应该注意判断的条件: 4 还有可能计算得到结果超了long long直接变成负数所以应该对或则个进行判断

hdu 1238 Substrings

点击打开链接hdu 1238 思路:kmp+暴力枚举子串 分析: 1 题目要求找到一个子串x,满足x或x的逆串是输入的n个字符串的子串,求最大的x,输出x的长度 2 题目的n最大100,每一个字符串的最大长度为100,那么暴力枚举子串就是o(n^2)才10000肯定是不会超时的,但是由于这里涉及到了逆串的问题,所以我们应该还要求出n个子串的逆串,然后在求最大的x. 代码: #include<iostream> #include<algorithm> #include<cstd