timus_1002_kmp_dijkstra

题目描述:

给定字母与数字的映射关系:

1 ij    2 abc   3 def

4 gh    5 kl    6 mn

7 prs   8 tuv   9 wxy

        0 oqz

根据输入的数字字符串,和已经存在的字符串词典,求出符合给出的数字字符串的字符串序列,要求这个序列中字符串的个数最少

输入:

数字字符串

字典中包含的字符串个数

字符串 …

有多个case输入,数字字符串为-1结束所有的case输入

7325189087

5

it

your

reality

real

our

4294967296

5

it

your

reality

real

our

-1

输出:

reality our

No solution.

输出满足条件的任意一组字符串序列,如果没有满足条件的,输出No solution.

解题思路:

将目标数字串的下标作为图的顶点。对于给定的字典中的每个字符串,根据映射表转化为数字串,通过KMP算法,将这些数字串与输入的目标数字串匹配,获得匹配项的下标s,e,并认为顶点s-1与顶点e是有一条长度为1的边,如果有多条相同的边,取一条就可以了。对于不匹配的字符串直接忽略。题目所求就是找出从顶点0到顶点n-1的最小路径长度(n为目标数字串数字的个数)。

代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 //数字与字母关系映射表
  6 char table[26] = {'2', '2', '2', '3', '3', '3', '4', '4', '1', '1', '5', '5', '6', '6', '0', '7', '0', '7', '7', '8', '8', '8', '9', '9', '9', '0'};
  7 
  8 //存放输入的数字串
  9 char digital[101]; 
 10 int len_digital;//输入字符串的长度
 11 
 12 //临时存放输入的字符串
 13 char temp_string[51], temp_input[51];
 14 //输入的字母在输入数字串中的位置表示
 15 char *position[100][100];
 16 
 17 //字典中单词的个数
 18 int n;
 19 //最小跳数的路径
 20 int path[100];
 21 //0顶点到其他顶点的距离
 22 int distance[100];
 23 int flag[100];//标记哪些顶点已经找到了最短路径
 24 
 25 #define INFINITE 1000000
 26 //打印答案
 27 void print_ans(int n)
 28 {
 29     if (path[n] == 0)
 30     {
 31         printf("%s ", position[0][n]);
 32         return ;
 33     }
 34     print_ans(path[n]);
 35     printf("%s ", position[path[n] + 1][n]);
 36 }
 37 //dijkstra算法
 38 void dijkstra()
 39 {
 40     int i,j;
 41 
 42     path[0] = -1;
 43     distance[0] = 0;
 44     flag[0] = 1;
 45     //初始化
 46     for (i = 1; i < len_digital; i ++)
 47     {
 48         path[i] = 0;    
 49         if (position[0][i])
 50         {
 51             distance[i]    = 1;
 52         }
 53         else
 54         {
 55             distance[i]    = INFINITE; 
 56         }
 57         flag[i] = 0;
 58     }
 59     //查找最短路径
 60     for (i = 1; i < len_digital; i ++)    
 61     {
 62         int min = INFINITE,k; 
 63         for (j = 1; j < len_digital; j ++) {
 64             if (!flag[j] && distance[j] < min)        
 65             {
 66                 min = distance[j];
 67                 k = j;
 68             }
 69         }
 70         if (min == INFINITE)
 71             break;
 72         flag[k] = 1;
 73         //printf("%d : %d\n", k, distance[k]);
 74         //松弛边
 75         for (j = k + 1; j < len_digital; j ++)
 76         {
 77             if (!flag[j] && position[k + 1][j] && distance[k] + 1 < distance[j])
 78             {
 79                 distance[j]    = distance[k] + 1;
 80                 path[j] = k;
 81             }
 82         }
 83     }
 84 }
 85 //获得最长长度k
 86 void computer_prefix_fuction(int prefix_func[])
 87 {
 88     int k,q;
 89 
 90     k = 0;
 91     prefix_func[0] = 0;
 92     q = 2;
 93     while (temp_string[q - 1])
 94     {
 95         while (k > 0 && temp_string[k] != temp_string[q - 1])    
 96             k = prefix_func[k - 1];
 97         if (temp_string[k] == temp_string[q - 1])
 98             k ++;
 99         prefix_func[q - 1] = k;
100         q ++;
101     }
102 }
103 //KMP算法
104 void kmp_matcher()
105 {
106     int q,i,prefix_func[51];
107 
108     computer_prefix_fuction(prefix_func);
109     i = 0;//计数
110     q = 0;//匹配的字符数
111     while (digital[i])    
112     {
113         while (q > 0 && temp_string[q] != digital[i])    
114             q = prefix_func[q - 1];
115         if (temp_string[q] == digital[i])
116             q ++;
117         if (! temp_string[q])
118         {
119             //匹配成功    
120             if (! position[i - q + 1][i])    
121             {
122                 position[i - q + 1][i] = (char *)malloc(sizeof(char) * (q + 1));
123                 strcpy(position[i - q + 1][i], temp_input);
124                 //printf("%s:%d ---> %d\n", temp_string, i - q + 1, i);
125             }
126             //匹配下一个
127             i = i - q + 1;
128             q = 0;
129         }    
130         i ++;
131     }
132 }
133 int main(void)
134 {
135     int i,j;
136 
137     while (1)    
138     {
139         //输入数据    
140         scanf("%s", digital);            
141         if (digital[0] == '-') 
142             break;
143         len_digital = strlen(digital);
144         scanf("%d", &n);        
145         //初始化position表
146         for (i = 0; i < len_digital; i ++)    
147             for (j = i; j < len_digital; j ++)
148                 position[i][j] = NULL;
149         
150         for (i = 0; i < n; i ++)
151         {
152             scanf("%s", temp_input);    
153             j = 0;
154             while (temp_input[j])    
155             {
156                 temp_string[j] = table[temp_input[j] - 'a'];
157                 j ++;
158             }
159             temp_string[j] = 0;
160             //获得输入字符串在目标数字串的位置,并将其填入position表中
161             kmp_matcher();
162         }    
163 
164         //使用dijkstra算法计算从位置0到位置n-1的最小跳数
165         dijkstra();
166         if (distance[len_digital - 1] == INFINITE)
167         {
168             printf("No solution.\n");    
169         }
170         else
171         {
172             print_ans(len_digital - 1);    
173             printf("\n");
174         }
175     }
176     return 0;
177 }

 

posted @ 2013-01-19 16:37  在于思考  阅读(356)  评论(0编辑  收藏  举报