Topic links
1002. Phone Numbers
Test instructions
In real life, you often encounter many, many, and longer numbers. You need to remember this type of number. For example, the following illustration, dividing letters into specific numbers is an easy way to remember numbers:
1 ij 2 abc 3 def4 gh 5 kl 6 mn7 prs 8 tuv 9 wxy0 oqz
In this way: each word or phrase can be replaced by a specific set of numbers, so you can remember the phone number only by remembering some words. If you can find a simple relationship between a word and a personal phone number, it is attractive. For example, one of your any player ID's phone numbers is 941837296, you can use Whitepawn instead, or you can use Buuldog to replace your favorite teacher's phone number: 2855304.
Problem
For a given number and a given list of words, find the shortest word sequence (that is, get a word as short as possible instead of the corresponding number). This correspondence requires that the relationship described be met.
Input
Enter test data that contains several groups. The first line of each test pilot is the phone number you want to remember. This number has a maximum of 100 digits. The second line of the test is the total number of words (50,000 maximum). Each of the following lines contains only one word and the maximum word length is limited to 50 letters. The size of the entire input file does not exceed 300KB. The last line of the input file takes 1 as the end flag.
Output
The shortest word sequence found for each behavior of the output file. Each word is separated by a space. If there is no solution, output "no solution." If more than one word satisfies a condition, you can select either Word output from it.
Sample input
73251890875ityourrealityrealour42949672965ityourrealityrealour-1
Output
reality ourNo solution.
Ideas
First, because each letter corresponds to a unique number, we can completely convert all the given words into a sequence of numbers.
So the problem now is to use the fewest number strings to make up the main string, and we use KMP to find out where each number string matches in the main string.
If the matching is successful, then the matching end-to-end position in the main string can be regarded as a one-way edge with a weight of 1, and the problem can be converted to the shortest-0~n problem.
Because the priority of each side of the problem is determined, so directly with the DP solution can be.
Code
#include <iostream>#include <cstring>#include <math.h>#include <cstdio>#include <stack>using namespace STD;Const intN =109;Const intM =50009;intP[n], D[n], v[n];intG[n][n];intFa[n];intL[M];Chars[ -], z[m][ -];intt[ -] = {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};intnxt[ -];voidGetNext (intD[],intLength) {nxt[0] =0; for(intI=1, k=0; i<length; i++) { while(k && d[i]! = d[k]) k = nxt[k-1]; Nxt[i] = d[i] = = D[k]? ++k:0; }}voidKmpintB[],intD[],intLenintLengthintPOS) {getNext (d, length); for(intI=0, k=0; i<len; i++) { while(k>0&& d[k]! = p[i]) k = nxt[k-1];if(D[k] = = P[i]) k++;if(k = = length) g[i-length+1][i+1] = pos; }}BOOLSolveintLen) {memset(V,0x3f,sizeof(v)); v[0] =0; for(intI=0; i<len; i++) for(intj=i+1; j<=len; J + +)if(G[i][j]! =-1&& v[i]+1< V[j]) {v[j] = V[i] +1; FA[J] = G[i][j]; }returnV[len] <0x3f3f3f3f;}voidPrintintNow) {if(Now-l[fa[now]) >0) {print (Now-l[fa[now]]);printf(" "); }printf('%s ', Z[fa[now]]);}intMain () {intN while(~scanf('%s ', s)) {if(s[0] =='-') Break;memset(g,-1,sizeof(g));intLen =strlen(s); for(intI=0; i<len; i++) P[i] = s[i]-' 0 ';scanf("%d", &n); for(intI=0; i<n; i++) {scanf('%s ', Z[i]); L[i] =strlen(Z[i]); for(intj=0; j<l[i]; J + +) D[j] = t[z[i][j]-' A ']; KMP (P, D, Len, L[i], i); }if(Solve (len)) print (LEN);Else printf("No solution.");printf("\ n"); }return 0;}
Timus 1002. Phone Numbers (kmp& dynamic planning)