In the present world you frequently meet a lot of call numbers and they are going to be longer and longer. You need to remember such a kind of numbers. One method to do it in an easy way is to assign letters to digits as shown in the following picture:
1 ij    2 abc   3 def
4 gh 5 kl 6 mn
7 prs 8 tuv 9 wxy
0 oqz
This way every word or a group of words can be assigned a unique number, so you can remember words instead of call numbers. It is evident that it has its own charm if it is possible to find some simple relationship between the word and the person itself. So you can learn that the call number 941837296 of a chess playing friend of yours can be read as WHITEPAWN, and the call number 2855304 of your favourite teacher is read BULLDOG.
Write a program to find the shortest sequence of words (i.e. one having the smallest possible number of words) which corresponds to a given number and a given list of words. The correspondence is described by the picture above.

Input

Input contains a series of tests. The first line of each test contains the call number, the transcription of which you have to find. The number consists of at most 100 digits. The second line contains the total number of the words in the dictionary (maximum is 50 000). Each of the remaining lines contains one word, which consists of maximally 50 small letters of the English alphabet. The total size of the input doesn't exceed 300 KB. The last line contains call number −1.

Output

Each line of output contains the shortest sequence of words which has been found by your program. The words are separated by single spaces. If there is no solution to the input data, the line contains text “No solution.”. If there are more solutions having the minimum number of words, you can choose any single one of them.
 
Link:http://acm.timus.ru/problem.aspx?space=1&num=1002
题目大意:每个字母有对应的数字,那么,为了方便电话号码的记忆,我们可以把这些数字换成多个单词来方便记忆。现在给出一串数字,和多个单词,要求用最少的单词来表示出所有的数字,有多个答案任意给出一个即可。
思路:乍眼看去好像有点小难……仔细想想,首先,因为每个字母都对应着一个数字,可以把这些字母都替换成数字,这样就变成了数字与数字之间的匹配。
然后,题目可以解释为:给你多个字符串(只包含数字),用最少的字符串组成一个特定的字符串。
于是,我们可以发现每个字符串所能覆盖的位置都是固定的,用KMP算法可以把他们都找出来。
这个是不是有点像最短路呢?对于每一个字符串,若它能覆盖的位置是从 i 到 j,那么连一条边i→j+1。
从0~n做最短路,选什么算法随意,当然既然是个DAG,顺序还是固定的,直接DP式地做这个最短路即可。
然后递归输出答案,解决。
 
代码(0.031S):
 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std; const int MAXV = ;
const int MAXS = ;
const int MAXL = ;
const int MAXE = MAXS * MAXL; int number[] = {, , , , , , , , , , , , , , , , , , , , , , , , , };
int mat[MAXV][MAXV], pre[MAXV], ecnt, n, k;
int s[MAXS][MAXL], src[MAXV], len[MAXS];
char ans[MAXS][MAXL], str[MAXV]; void init() {
memset(mat, -, sizeof(mat));
} void add_edge(int u, int v, int pos) {
mat[u][v] = pos;
} int dis[MAXV]; bool SPFA() {
memset(dis, 0x3f, sizeof(dis));
dis[] = ;
for(int i = ; i < n; ++i) {
for(int j = i + ; j <= n; ++j) {
if(~mat[i][j] && dis[i] + < dis[j]) {
pre[j] = mat[i][j];
dis[j] = dis[i] + ;
}
}
}
return dis[n] <= n;
} void getFail(int P[], int m, int f[]) {
f[] = f[] = ;
for(int i = ; i < m; ++i) {
int j = f[i];
while(j && P[i] != P[j]) j = f[j];
f[i + ] = (P[i] == P[j] ? j + : );
}
} void KMP(int T[], int n, int P[], int m, int f[], int pos) {
getFail(P, m, f);
for(int i = , j = ; i < n; ++i) {
while(j && P[j] != T[i]) j = f[j];
if(P[j] == T[i]) ++j;
if(j == m) add_edge(i - m + , i + , pos);
}
} void print(int pos) {
if(pos - len[pre[pos]] != ) {
print(pos - len[pre[pos]]);
putchar(' ');
}
printf("%s", ans[pre[pos]]);
} int fail[MAXL]; int main() {
while(scanf("%s", str) != EOF) {
if(strcmp(str, "-1") == ) break;
n = strlen(str);
for(int i = ; i < n; ++i) src[i] = str[i] - '';
scanf("%d", &k);
for(int i = ; i < k; ++i) {
scanf("%s", ans[i]);
len[i] = strlen(ans[i]);
for(int j = ; j < len[i]; ++j) s[i][j] = number[ans[i][j] - 'a'];
}
init();
for(int i = ; i < k; ++i)
KMP(src, n, s[i], len[i], fail, i);
if(SPFA()) print(n), puts("");
else puts("No solution.");
}
}

URAL 1002 Phone Numbers(KMP+最短路orDP)的更多相关文章

  1. 1002 Phone Numbers 解题报告

    1002. Phone Numbers Time limit: 2.0 secondMemory limit: 64 MB In the present world you frequently me ...

  2. 递推DP URAL 1586 Threeprime Numbers

    题目传送门 /* 题意:n位数字,任意连续的三位数字组成的数字是素数,这样的n位数有多少个 最优子结构:考虑3位数的数字,可以枚举出来,第4位是和第3位,第2位组成的数字判断是否是素数 所以,dp[i ...

  3. 递推DP URAL 1009 K-based Numbers

    题目传送门 题意:n位数,k进制,求个数分析:dp[i][j] 表示i位数,当前数字为j的个数:若j==0,不加dp[i-1][0]; 代码1: #include <cstdio> #in ...

  4. ural 2070. Interesting Numbers

    2070. Interesting Numbers Time limit: 2.0 secondMemory limit: 64 MB Nikolay and Asya investigate int ...

  5. ural 1150. Page Numbers

    1150. Page Numbers Time limit: 1.0 secondMemory limit: 64 MB John Smith has decided to number the pa ...

  6. URAL 1056 Computer Net(最短路)

    Computer Net Time limit: 2.0 secondMemory limit: 64 MB Background Computer net is created by consecu ...

  7. URAL 2034 Caravans(变态最短路)

    Caravans Time limit: 1.0 secondMemory limit: 64 MB Student Ilya often skips his classes at the unive ...

  8. URAL 2031. Overturned Numbers (枚举)

    2031. Overturned Numbers Time limit: 1.0 second Memory limit: 64 MB Little Pierre was surfing the In ...

  9. URAL 1012 K-based Numbers. Version 2(DP+高精度)

    题目链接 题意 :与1009一样,不过这个题的数据范围变大. 思路:因为数据范围变大,所以要用大数模拟,用java也行,大数模拟也没什么不过变成二维再做就行了呗.当然也可以先把所有的都进行打表,不过要 ...

随机推荐

  1. There is no tracking information for the current branch

    There is no tracking information for the current branch. Please specify which branch you want to mer ...

  2. Let's Encrypt这个免费的证书签发服务

    使用的是Let's Encrypt这个免费的证书签发服务,按照这里的教程一步步照着来,很快就完成了. 迁移过程总体来说比较顺利,只是遇到了两个不大不小的坑.一个是域名的跳转问题,迁移完成以后对于所有h ...

  3. Android HttpHeader的坑

    昨天遇到一个问题,代码如下: private String getSessionId(HttpResponse response) { // TODO Auto-generated method st ...

  4. SQL Server中的Image数据类型的操作

    原文:SQL Server中的Image数据类型的操作 准备工作,在库Im_Test中建立一张表Im_Info,此表中有两个字段,分别为Pr_Id (INT),Pr_Info (IMAGE),用来存储 ...

  5. SQLSERVER 16进制转10进制

    原码.补码.反码参考: http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 进制转换参考: http://ww ...

  6. magento

     打开 magento/app/code/core/Mage/Core/Model/Session/Abstract/varien.php//if (isset($cookieParams['doma ...

  7. Ⅰ.net通信指前提

    ①大概搜索了一下,一般提到了这三种居多: Webservice:基于B/S的,可以对外发布方法 Socket:一种网络数据交换模型,Socket接口是TCP/IP网络的API,有三个主要因素:地址.端 ...

  8. JS判断浏览器是否安装flash插件

    1.直接判断是否有flash插件 var myFlash = (function(){ if(typeof window.ActiveXObject != "undefined") ...

  9. android apk简单反编译

    1. 查看或者提取资源文件:     使用谷歌官方工具apktool,命令行如下: apktool d xxx.apk xxx_decode d代表反编译,xxx.apk为你要反编译的apk,xxx_ ...

  10. qt QMessageBox QInputDialog

    最近用到了QMessgaeBox和QInputDialog,QMessageBox用于提示,警告等消息,QInputDialog给用户弹出输入对话框. 参考链接 http://chenboqiang. ...