题目大意:
给出若干摩斯密码,再给出若干个单词,最后给出一些暗文,问这些暗文最可能是哪个单词?
如果暗文能够跟多个单词精确匹配,那么输出第一个并在后面加上一个!。
如果只能够跟一个精确匹配,那么就直接输出。
如果不能够精确匹配,那么就寻找与当前暗文最相似的一个单词,并在后面加上一个?,如果有多个就输出任意一个即可。
这里最相似的单词就是这个暗文添加或者删除一些摩斯码之后可以对应成相应的单词
思路:
利用一个map保存每个单词与对应摩斯码的映射
再用一个map保存每一个单词与其摩斯码的映射
接下来输入若干个要匹配的摩斯码,直接判断相似度即可。所谓相似,其实就是看看一个摩斯码是不是一个摩斯码的前缀。
代码:
#include <map>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int idx;
string s , t , ss[N];
map < char , string >code;
map <string , string > dirt;
inline void init()
{
idx = 0;
code.clear();
dirt.clear();
}
int main(void)
{
while(cin >> s)
{
init();
while(s != "*")
{
cin >> t;
code[s[0]] = t;//保存每个字母的摩斯码
cin >> s;
}
while(cin >> s && s != "*")
{
t.clear();
ss[idx ++] = s;
for(int i = 0 ; i < s.length() ; ++ i) t += code[s[i]];
dirt[s] = t;//保存每个单词的摩斯码
}
while(cin >> s && s != "*")
{
int cnt = 0 , index = -1 , minv = 0x3f3f3f3f;
for(int i = 0 ; i < idx ; ++ i)
{
t = dirt[ss[i]];//先将第i个单词转成对应的摩斯码
if(s == t)//如果这两个摩斯码是相通的
{
index = cnt == 0 ? i : index;
cnt ++;
minv = 0;
}
//如果不同,那么就去判断一个摩斯码是不是另一个摩斯码的前缀
else if(t.find(s) == 0 && t.length() - s.length() < minv)
{
minv = t.length() - s.length();
index = i;
}
else if(s.find(t) == 0 && s.length() - t.length() < minv)
{
minv = s.length() - t.length();
index = i;
}
}
//输出
cout << ss[index];
if(cnt > 1) cout << "!" << endl;
else if(cnt == 1) cout << endl;
else cout << "?" << endl;
}
}
return 0;
}