UVa 508 Morse Mismatches(莫尔斯电码)

来源:互联网 发布:李荣浩戒烟知乎 编辑:程序博客网 时间:2024/04/29 22:06

Description

Download as PDF


  Morse Mismatches 

Samuel F. B. Morse is best known for the coding scheme that carries his name. Morse code is still used in international radio communication. The coding of text using Morse code is straightforward. Each character (case is insignificant) is translated to a predefined sequence of dits and dahs (the elements of Morse code). Dits are represented as periods (``.'') and dahs are represented as hyphens or minus signs (``-''). Each element is transmitted by sending a signal for some period of time. A dit is rather short, and a dah is, in perfectly formed code, three times as long as a dit. A short silent space appears between elements, with a longer space between characters. A still longer space separates words. This dependence on the spacing and timing of elements means that Morse code operators sometimes do not send perfect code. This results in difficulties for the receiving operator, but frequently the message can be decoded depending on context.


In this problem we consider reception of words in Morse code without spacing between letters. Without the spacing, it is possible for multiple words to be coded the same. For example, if the message ``dit dit dit'' were received, it could be interpreted as ``EEE'', ``EI'', ``IE'' or ``S'' based on the coding scheme shown in the sample input. To decide between these multiple interpretations, we assume a particular context by expecting each received word to appear in a dictionary.


For this problem your program will read a table giving the encoding of letters and digits into Morse code, a list of expected words (context), and a sequence of words encoded in Morse code (morse). These morse words may be flawed. For each morse word, your program is to determine the matching word from context, if any. If multiple words from context match morse, or if no word matches perfectly, your program will display the best matching word and a mismatch indicator.


If a single word from context matches morse perfectly, it will be displayed on a single line, by itself. If multiple context words exist for a given morse, the first matching word will be displayed followed by an exclamation point (``!'').


We assume only a simple case of errors in transmission in which elements may be either truncated from the end of a morse word or added to the end of a morse word. When no perfect matches for morse are found, display the word from context that matches the longest prefix of morse, or has the fewest extra elements beyond those in morse. If multiple words in context match using these rules, any of these matches may be displayed. Words that do not match perfectly are displayed with a question mark (``?'') suffixed.


The input data will only contain cases that fall within the preceding rules.

Input 

The Morse code table will appear first and consists of lines each containing an uppercase letter or a digit C, zero or more blanks, and a sequence of no more than six periods and hyphens giving the Morse code for C. Blanks may precede or follow the items on the line. A line containing a single asterisk (``*''), possibly preceded or followed by blanks, terminates the Morse code table. You may assume that there will be Morse code given for every character that appears in the context section.


The context section appears next, with one word per line, possibly preceded and followed by blanks. Each word in context will contain no more than ten characters. No characters other than upper case letters and digits will appear. Thered will be at most 100 context words. A line containing only a single asterisk (``*''), possibly preceded or followed by blanks, terminates the context section.


The remainder of the input contains morse words separated by blanks or end-of-line characters. A line containing only a single asterisk (``*''), possibly preceded or followed by blanks, terminates the input. No morse word will have more than eighty (80) elements.

Output 

For each input morse word, display the appropriate matching word from context followed by an exclamation mark (``!'') or question mark (``?'') if appropriate. Each word is to appear on a separate line starting in column one.

Sample Input 

A       .-B       -...C       -.-.D       -..E       .F       ..-.G       --.H       ....I       ..J       .---K       -.-L       .-..M       --N       -.O       ---P       .--.Q       --.-R       .-.S       ...T       -U       ..-V       ...-W       .--X       -..-Y       -.--Z       --..0       ------1       .-----2       ..---3       ...--4       ....-5       .....6       -....7       --...8       ---..9       ----.*ANEARTHQUAKEEATGODHATHIMREADYTOWHATWROTH*.--.....--   .....--....--.----..   .--.-.----...--.....--   .--...-.-.-....--.-..-.--.-...--   .-...--..-.------        ..--*

Sample Output 

WHATHATHGODWROTH?WHATANEARTHQUAKEEAT!READYTOEAT!

因为懒得看英文题目(事实证明不看题的代价是惨痛的= =),所以就直接看紫书(算法入门经典第2版)上题目的描述,结果无限WA,捣鼓了一天还是不对,最后硬着头皮看了遍英文题目,又从网上找了个标程研究了一下午,发现紫书上的描述竟然是错的。。。= =

这个题当把细节理解清楚了以后,其实很简单,就是因为自己题意理解不清,对题目的曲解太大了,所以才会拖延了这么长时间,看来以后需要耐心仔细地读英文题了。。。这题的意思是给定一些莫尔斯编码,给定一些已知字典,给定一些编码,求解这些编码的对应原文,如果可以精确匹配,则直接输出原单词,如果有多个可精确匹配的结果,则输出匹配结果里字典序最小的单词(紫书上说输出任意一个,这是错误的)并在末位加上“!”;如果无法精确匹配,则可以在编码的末尾增加或删除一些字符后匹配单词(增删应尽量小,就是找到增删最少的模糊匹配),无论增删后匹配一个还是多个,最后都要加上“?”,如果有多个模糊匹配结果(增删数相等),则输出字典序最小的匹配结果;如果无精确匹配也无模糊匹配结果,则输出整个给定字典里字典序最小的那个单词。

实现方面,看网上标程是用映射写的(也难怪自己没发现字典序这个关键词,映射里的元素直接就是排好序的,用映射看来很简单啊。。。= =),我用的是简单的字符数组,一个用来存给定的莫尔斯电码,一个结构体包含两个字符数组,一个存给定单词明文,并存下按莫尔斯电码翻译后的密文,重载小于运算,使字典按字典序排好,对于每个给定的编码,匹配字典里所有单词的密文,判断精确匹配的个数,若为0则开始模糊匹配,代码如下:

#include <iostream>#include <algorithm>#include <cstring>using namespace std;struct text{char Plaintext[20];//明文char Ciphertext[100];//密文bool operator < (const text a)const{return strcmp(Plaintext,a.Plaintext)<0;//重载小于运算,将给定字典元素按字典序排序}}str[101];char morse[128][10],code[101];//morse存储莫尔斯码,code存储待解编码int n=0;int toMatch(int &p);//传入p的引用,获得匹配数并使p指向匹配位置int main(){ios::sync_with_stdio(false);char c;while(cin>>c,c!='*')//输入莫尔斯码cin>>morse[(int)c];while(cin>>str[n].Plaintext,str[n].Plaintext[0]!='*')//输入给定字典元素{int len=strlen(str[n].Plaintext);str[n].Ciphertext[0]=0;for(int i=0;i<len;i++)//将给定字典元素按莫尔斯码翻译成密文存储strcat(str[n].Ciphertext,morse[(int)str[n].Plaintext[i]]);n++;}sort(str,str+n);//将所有字典字典序排序while(cin>>code,code[0]!='*'){int p,cont=toMatch(p);//获得匹配数量if(cont)cout<<str[p].Plaintext<<(cont==1?"":"!")<<endl;//多个精确匹配要额外输出叹号else{int minn=10000,pi=-1,lencode=strlen(code);for(int i=0;i<n;i++)//模糊匹配时,遍历字典集{int len=strlen(str[i].Ciphertext);if(lencode>len&&(strstr(code,str[i].Ciphertext)==code))//如果字典里某元素是待解编码的子串,且匹配位置为待解编码首字符,说明该字典元素可由待解编码删减字符得到{if((lencode-len)<minn)//要求删减数量尽量少{minn=lencode-len;pi=i;}}else if(lencode<len&&(strstr(str[i].Ciphertext,code)==str[i].Ciphertext))//如果待解编码是字典里某元素的子串,且匹配位置为字典某元素的字符,说明该字典元素可由待解编码增加字符得到{if((len-lencode)<minn)//要求增加数量尽量少{minn=len-lencode;pi=i;}}}if(pi==-1)//若模糊匹配也无任何结果,则输出字典序最小的元素并加问号{cout<<str[0].Plaintext<<"?"<<endl;}else//可匹配则输出,并且末尾加问号cout<<str[pi].Plaintext<<"?"<<endl;}}return 0;}int toMatch(int &p){int cont=0;for(int i=0;i<n;i++)if(!strcmp(code,str[i].Ciphertext)){if(!cont)//匹配时输出字典序靠前的,所以p指向第一个匹配的就OKp=i;cont++;}return cont;//返回精确匹配的个数}


0 0
原创粉丝点击