JOJ 1058 T9

题目:http://acm.jlu.edu.cn/joj/showproblem.php?pid=1058

 

算法:Trie树,广度优先搜索

思路:把字典建成一个Trie树,每次处理一个按键序列时,都建立一个队列,循环处理,初始循环时,Trie的根结点入队,每次循环时,遍历当前在队列中的每一个结点的所有子结点,把它们的子结点当中与当前所处理的按键相同的结点入队,全部入队完毕后,选中当前队列中的优先级最高的结点,输出从根结点到该结点的路径,然后开始新一轮循环,处理按键序列中的下一个按键。

这个题目还可以用另一种方法来做,就是在读入字典的时候,同时生成当前单词的按键序列。然后读入按键序列后,在字典中顺序查找,在查找过程中,把前缀相同的单词的优先级要累加起来。感觉还是使用Trie树更简单些。

使用Trie树的代码如下:

  1. /* {JOJ1058:T9}
  2.  * Date & Time: Thu Oct 09 19:42:13 2008
  3.  * File: 1058.c
  4.  * Author: WangHaibin
  5.  * Platform: windows xp sp2, emacs 22.1, gcc, gdb
  6.  *
  7.  * Algorithm: Trie树,广度搜索
  8.  *
  9.  * State: Acceptd, 0.00s, 416K
  10.  * */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. typedef struct _tn {
  15.     char letter;
  16.     int frequency;
  17.     char belongTo;
  18.     struct _tn *child, *brother, *parent;
  19.     char isComplete;
  20. } TrieNode;
  21. TrieNode *root;
  22. char belongTo[26] = {'2','2','2','3','3','3','4','4','4','5','5','5','6','6','6',
  23.              '7','7','7','7','8','8','8','9','9','9','9'};
  24. void insert(const char* word, int freq) {
  25.     TrieNode *p = root, *oldBrother = NULL, *dest = root->child;
  26.     int k = 0, len = strlen(word);
  27.     for(k = 0; k < len; k++) {
  28.     while(dest != NULL && dest->letter != word[k]) {
  29.         oldBrother = dest, dest = dest->brother;
  30.     }
  31.     if(dest) {
  32.         dest->frequency += freq;
  33.     } else {
  34.         /* dest is NULL, word[0] not found */
  35.         dest = (TrieNode*)malloc(sizeof(TrieNode));
  36.         dest->letter = word[k];
  37.         dest->frequency = freq;
  38.         dest->parent = p;
  39.         dest->brother = NULL;
  40.         dest->child = NULL;
  41.         dest->belongTo = belongTo[word[k]-'a'];
  42.         dest->isComplete = 0;
  43.         if(oldBrother) {
  44.         oldBrother->brother = dest;
  45.         } else {
  46.         /* oldBrother为空,说明p的子树为空 */
  47.         p->child = dest;
  48.         }
  49.     }
  50.     p = dest;
  51.     dest = p->child;
  52.     oldBrother = NULL;
  53.     }
  54.     p->isComplete = 1;
  55. }
  56. void solve(const char* seq) {
  57.     TrieNode *queue[1024];
  58.     int front = 0, rear = 0, k = 0, i, j, maxfreq;
  59.     TrieNode *curLayer;
  60.     char path[128] = {0};
  61.     queue[rear++] = root;
  62.     while(seq[k] != '1') {
  63.     i = rear - front;
  64.     for(j = 1; j <= i; j++) {
  65.         curLayer = queue[front]->child;
  66.         front++;
  67.         while(curLayer) {
  68.         if(curLayer->belongTo == seq[k]) {
  69.             queue[rear++] = curLayer;
  70.         }
  71.         curLayer = curLayer->brother;
  72.         }
  73.     }
  74.     if(front == rear) {
  75.         /* queue is empty */
  76.         printf("MANUALLY/n");
  77.         k++;
  78.         continue;
  79.     }
  80.     for(i = front + 1, maxfreq = queue[front]->frequency, j = front; i < rear; i++) {
  81.         if(queue[i]->frequency > maxfreq) {
  82.         maxfreq = queue[i]->frequency;
  83.         j = i;
  84.         }
  85.     }
  86.     curLayer = queue[j]->parent;
  87.     i = 126;
  88.     path[i] = queue[j]->letter;
  89.     while(curLayer != root) {
  90.         path[--i] = curLayer->letter;
  91.         curLayer = curLayer->parent;
  92.     }
  93.     printf("%s/n", path+i);
  94.     k++;
  95.     }
  96. }
  97. void deleteTree(TrieNode* t) {
  98.     if(t != NULL) {
  99.     deleteTree(t->child);
  100.     deleteTree(t->brother);
  101.     free(t);
  102.     }
  103. }
  104. int main() {
  105.     int n, w, p, m, i;
  106.     char word[128], seq[128];
  107.     root = (TrieNode*)malloc(sizeof(TrieNode));
  108.     root->child = NULL;
  109.     root->brother = NULL;
  110.     /*freopen("in.txt", "r", stdin);*/
  111.     scanf("%d", &n);
  112.     for(i = 1; i <= n; i++) {
  113.     scanf("%d", &w);
  114.     while(w--) {
  115.         scanf("%s%d", word, &p);
  116.         insert(word, p);
  117.     }
  118.     scanf("%d", &m);
  119.     printf("Scenario #%d:/n", i);
  120.     while(m--) {
  121.         scanf("%s", seq);
  122.         solve(seq);
  123.         printf("/n");
  124.     }
  125.     deleteTree(root->child);
  126.     root->child = NULL;
  127.     root->brother = NULL;
  128.     printf("/n");
  129.     }
  130.     return 0;
  131. }

你可能感兴趣的:(Algorithm,算法,null,insert,Path,emacs)