建立字符到对应Morse密码的映射map1。
每输入一个单词,通过map1将每一个字符翻译成Morse密码,建立所有密码到对应单词的映射map2。
对应输入的Morse密码M,在map2中查找是否有该密码和对应单词,单词数大于1多输出一个"!"。不存在对应,查找符合条件的增删Morse密码。在M的基础上增加或者删除和已知map密码相同,那么M不正是map密码的前缀,或者相反。找到增删密码长度差最小的那个输出即可。可以使用map<int, string>存放int放长度差,string存储单词,map本身就是按key排序的,直接输出第一个元素即可。
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
map<char, string> morse;//字符到Morse密码的映射
map<string, vector<string> > word;//Morse密码串到单词的映射
/*
* 判断a是否是b的前缀
* @prama a 字符串a
* @prmaa b 字符串b
* @return a是b的前缀返回true,否则返回false
*/
bool isPre(const string& a, const string& b)
{
return a.size() < b.size() && b.compare(0, a.size(), a) == 0;
}
/*
* *对Morse密码串a的翻译
* @parma a Morse密码串
*/
void slove(const string& a)
{
if (word.count(a))//密码串与已知密码串匹配
{
auto v = word[a];
cout << v.front();//返回第一个
if (v.size() > 1) cout << "!";//匹配单词数大于1个
cout << endl;
return ;
}
map<int, string> ans;//模糊单词到单词的增删个数到单词的映射
for (auto p: word)
{
string tmp = p.first;//密码
//a与密码比较,如果a是密码的前缀,处理删除字符
//密码是a的前缀,处理增加字符
if (isPre(a, tmp)) ans[tmp.size() - a.size()] = p.second.front();
else if (isPre(tmp, a)) ans[a.size() - tmp.size()] = p.second.front();
}
//mp本身就是按key存放的,直接输出第一个元素即可
cout << ans.begin()->second << "?" << endl;
}
int main()
{
string a, b;
while (cin >> a && a != "*")
{
cin >> b;
morse[a[0]] = b;
}
while (cin >> a && a != "*")
{
b.clear();
for (auto x : a) b += morse[x];
word[b].push_back(a);//密码对应串
}
while (cin >> a && a != "*")
slove(a);
return 0;
}