原题


大家有木有看过带谍战剧?里面多数都有发电报的情节吧,有木有感觉滴滴答答地发报特别酷?
发报的那个东西,学名叫做“电键”,如图:

在这里插入图片描述
电键按下去之后,电路接通,就会发出声音,长短不同的声音组合,就形成了不同的编码,可以表示不同的信息~
汉字个数太多,所以汉字的编码是很复杂的。但是英文字母比较少,编码就容易多了
我们今天来研究一种国际通用的电报编码——莫尔斯码。
我们用“滴(Di~)”来模拟电键短按发出的声音,用一个点(dot)表示: .
用“答(Da~)”来模拟电键长按发出的声音,用一个短划(dash)表示: -
英文字母和数字的莫尔斯码是:

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 ----.
例如求救信号 SOS 的莫尔斯码就是: … — … (每个字母的编码中间空一格)
现在请将输入的编码转成文本、将输入的文本转成编码。
输入格式:
第一行为一个正整数N,
接下来N行,每行为不超过200个字符的文本或者编码。
我们把连续的一串字母或数字的组合称之为一个“单词”,输入的文本格式是:每个单词之间空一格,文本的首末两端没有空格,例如CQ CQ,文本仅有大写字母、数字、空格组成。
输入的编码的格式是:每个单词内的字母编码或数字编码之间空一格,每个单词之间用|分隔,例如 -.-. --.-|-.-. --.- (文本 CQ CQ的编码)


输出输入格式:


对每一行输入的文本或编码,采用相对应的格式,在一行中对应给出其编码或文本。

输入样例:

2
-.-. --.-|-.-. --.-|-.-. --.-|-… .|-… -… … … .-… .-|-… -… … … .-… .-|-.-
CQ CQ CQ DE BD5HLA BD5HLA K

输出样例:


CQ CQ CQ DE BD5HLA BD5HLA K
-.-. --.-|-.-. --.-|-.-. --.-|-… .|-… -… … … .-… .-|-… -… … … .-… .-|-.-

题意

给定字符与莫尔斯码的对应关系,要求将文本转换成编码,或将编码转换成文本。
和去年天梯赛的AI代码一样,忠实题意模拟即可


关系存储

这里可以用一个一维字符数组存单个字符,然后二维数组存莫尔斯码,但这在查找比较的时候较复杂,速度也慢。这里我用map存储,不过存入时代码比较多。

	map<char , string>m1;
	map<string , string>m2;
	
	freopen("output.txt" , "r" , stdin);
	string s1 , s2;
	while(cin>>s1>>s2)
	{
		cout<<"m1["<<"'"<<s1<<"']"<<" = "<<"\""<<s2<<"\";"<<endl;
		cout<<"m2["<<"\""<<s2<<"\"]"<<" = "<<"\""<<s1<<"\";"<<endl;
	}

这里直接运行上面这段程序,再将上面的关系复制进来,最后将输出的内容拷贝到编译器即可。

判断文本或者是编码

这里用“|”去区分文本或者是编码恐怕有失偏颇,万一编码只有一组岂不是同样没有“|”
所以采用“.”和“-”来进行区分。注意到有的编码只有“.”有的编码只有“-”,所以如果是文本的话,应该同时不含有“.”和“-”。

	bool flag = false;	
	if(str.find(".") == string :: npos && str.find("-") == string :: npos)
		flag = true;

这里可以用string 的find函数,string::npos就是空的意思。通过flag的值决定进行何种转换


文本转编码


因为刚刚用了map进行存储,所以只需要遍历输入进来的字符串即可,碰到字符直接输出对应的编码,碰到空格就输出"|",这里尤其注意什么时候输出空格。得是下一个字符不是字母才能输出空格,并且得保证判断的时候下标不越界,最后输出换行。

	for(int i = 0 ; i < str.length() ; i++)
	{
		if(str[i] != ' ')
		{
			cout<<m1[str[i]];
			if(i + 1 < str.length() && str[i + 1] != ' ')
				cout<<" ";
		}
			
		else	
			cout<<"|";
	}
	cout<<endl;

编码转文本


这里就比较复杂了,因为题目输入的是一整串文本,而我们需要的是其中一段一段才更好处理。这里可以用c++的sstream或者是c的ssprint,用于字符串的二次读入储存。我们观察到不同组的编码通过“|”分隔,但实际上我们处理的时候并没有很大价值,如果是换成空格分割会好些,但换成空格又和原本的空格产生歧义,所以这里考虑塞进一个不相干的字符进去,用于区别是否是同种字符,这里我采用“a”。

	while(str.find("|") != string :: npos)
		str.replace(str.find("|") , 1 , " a ");
	stringstream ss(str);
	int k = 0;
	while(ss >> str)
		s[k++] = str; 

这里把“|”替换成“ a ”,再把得到的字符串输入进一个字符串数组里。
举个例子,比如:-.-. --.-|-.-. --.-|-.-. --.-|
处理后

  1. s[0] = “-.-”.
  2. s[1] = “–.-”
  3. s[2] = “a”
  4. s[3] = “-.-.”
  5. s[4] = “–.-”
  6. s[5] = “a”
  7. s[6] = “-.-.”
  8. s[7] = “–.-”
  9. s[8] = “a”

这样我们处理起来就很方便了,不是a的话就直接输出对应的字符,是a就输出空格

	for(int i = 0 ; i < k ; i++)
	{
		if(s[i] != "a")
			cout<<m2[s[i]];
		else
			cout<<" ";
	}
	cout<<endl;

代码


//7-13 莫尔斯码(Morse Code) (15分)
#include<map>
#include<cstdio>
#include<sstream>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

map<char , string>m1;
map<string , string>m2;

int main()
{
// freopen("output.txt" , "r" , stdin);
// string s1 , s2;
// while(cin>>s1>>s2)
// {
// cout<<"m1["<<"'"<<s1<<"']"<<" = "<<"\""<<s2<<"\";"<<endl;
// cout<<"m2["<<"\""<<s2<<"\"]"<<" = "<<"\""<<s1<<"\";"<<endl;
// }

	m1['A'] = ".-";
	m2[".-"] = "A";
	m1['B'] = "-...";
	m2["-..."] = "B";
	m1['C'] = "-.-.";
	m2["-.-."] = "C";
	m1['D'] = "-..";
	m2["-.."] = "D";
	m1['E'] = ".";
	m2["."] = "E";
	m1['F'] = "..-.";
	m2["..-."] = "F";
	m1['G'] = "--.";
	m2["--."] = "G";
	m1['H'] = "....";
	m2["...."] = "H";
	m1['I'] = "..";
	m2[".."] = "I";
	m1['J'] = ".---";
	m2[".---"] = "J";
	m1['K'] = "-.-";
	m2["-.-"] = "K";
	m1['L'] = ".-..";
	m2[".-.."] = "L";
	m1['M'] = "--";
	m2["--"] = "M";
	m1['N'] = "-.";
	m2["-."] = "N";
	m1['O'] = "---";
	m2["---"] = "O";
	m1['P'] = ".--.";
	m2[".--."] = "P";
	m1['Q'] = "--.-";
	m2["--.-"] = "Q";
	m1['R'] = ".-.";
	m2[".-."] = "R";
	m1['S'] = "...";
	m2["..."] = "S";
	m1['T'] = "-";
	m2["-"] = "T";
	m1['U'] = "..-";
	m2["..-"] = "U";
	m1['V'] = "...-";
	m2["...-"] = "V";
	m1['W'] = ".--";
	m2[".--"] = "W";
	m1['X'] = "-..-";
	m2["-..-"] = "X";
	m1['Y'] = "-.--";
	m2["-.--"] = "Y";
	m1['Z'] = "--..";
	m2["--.."] = "Z";
	m1['0'] = "-----";
	m2["-----"] = "0";
	m1['1'] = ".----";
	m2[".----"] = "1";
	m1['2'] = "..---";
	m2["..---"] = "2";
	m1['3'] = "...--";
	m2["...--"] = "3";
	m1['4'] = "....-";
	m2["....-"] = "4";
	m1['5'] = ".....";
	m2["....."] = "5";
	m1['6'] = "-....";
	m2["-...."] = "6";
	m1['7'] = "--...";
	m2["--..."] = "7";
	m1['8'] = "---..";
	m2["---.."] = "8";
	m1['9'] = "----.";
	m2["----."] = "9";	
	
	int n;
	string str;
	string s[210];
 	cin>>n;
 	getchar();
 	while(n--)
 	{
 		getline(cin , str);
// cout<<s1<<endl;
		bool flag = false;	
		if(str.find(".") == string :: npos && str.find("-") == string :: npos)
			flag = true;
		
		if(flag)
		{
			for(int i = 0 ; i < str.length() ; i++)
			{
				if(str[i] != ' ')
				{
					cout<<m1[str[i]];
					if(i + 1 < str.length() && str[i + 1] != ' ')
						cout<<" ";
				}
					
				else	
					cout<<"|";
			}
			cout<<endl;
		}
		else
		{
			while(str.find("|") != string :: npos)
				str.replace(str.find("|") , 1 , " a ");
// cout<<str<<endl;
			stringstream ss(str);
			int k = 0;
			while(ss >> str)
				s[k++] = str; 
			
			for(int i = 0 ; i < k ; i++)
			{
				if(s[i] != "a")
					cout<<m2[s[i]];
				else
					cout<<" ";
			}
			cout<<endl;
		}
	}
	return 0; 
}