map не сохраняет ассоциацию по уже существующему ключу
Добрый день. Решаю задачу : "Два слова называются синонимами друг друга, если они имеют похожие значения. Реализуйте следующие операции над словарём синонимов: ADD word1 word2 — добавить в словарь пару синонимов (word1, word2). COUNT word — узнать количество синонимов слова word. CHECK word1 word2 — проверить, являются ли слова word1 и word2 синонимами. Слова word1 и word2 считаются синонимами, если среди запросов ADD был хотя бы один запрос ADD word1 word2 или ADD word2 word1. Замечание Для упрощения, будем считать, что синонимы не обладают транзитивностью, то есть, если A - синоним B, а B - синоним C, то из этого НЕ следует, что A - синоним C. Формат ввода Сначала вводится количество запросов Q, затем Q строк с описаниями запросов. Гарантируется, что в каждом запросе CHECK и ADD слова word1 и word2 различны. Все слова состоят лишь из латинских букв, цифр и символов подчёркивания. Формат вывода Для каждого запроса в соответствующей строке выведите ответ на него: В ответ на запрос COUNT word выведите единственное целое число — количество синонимов слова word. В ответ на запрос CHECK word1 word2 выведите строку YES, если word1 и word2 являются синонимами, и NO в противном случае."
Написал код,использующий контейнер map.
#include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;
void print_map(const map <string, string>& mp){
for(auto i : mp){
cout<<i.first<<" : "<<i.second<<endl;
}
}
void ADD(map <string, string>& mp, string word1, string word2){
mp[word1] = word2;
}
int COUNT(const map <string, string>& mp,string word){
int count_ = 0;
for(auto i : mp){
if(i.first == word || i.second == word)
count_++;
}
return count_;
}
bool CHECK( map <string, string>& mp, string word1, string word2){
if ( mp[word1] == word2 || mp[word2] == word1 ){
return true;
}
else
return false;
}
int main()
{
int Q;
string name_command,syn1,syn2;
map <string, string> mp;
cin >> Q;
for(int i = 0 ; i < Q;i++){
cin >> name_command;
if(name_command == "ADD"){
cin >> syn1 >> syn2;
ADD(mp, syn1, syn2);
}
if(name_command == "COUNT"){
cin >> syn1;
cout << COUNT(mp, syn1)<<endl;
}
if(name_command == "CHECK"){
cin >> syn1 >> syn2;
if(CHECK(mp, syn1, syn2)){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
}
print_map(mp);
}
Ошибка в том,что 6 тест вида :
3
ADD c++ rust
ADD c++ java
CHECK rust c++
Выдает "No" и это неправильно. Не понимаю,почему контейнер map не создает вторую "ассоциацию" между с++ и java, а затирает первую,меняя rust на java. Буду благодарен за помощь в исправлении бага.
Ответы (1 шт):
Потому что map - это по сути своей множество, в котором может быть только один одинаковый элемент (поскольку сравнение идет по ключу - один ключ).
Вам нужен либо multimap, когда может иметься множество элементов с одним ключом, либо, что мне кажется предпочтительнее,
map<string,vector<string>>
Так вы тоже сможете хранить в одном элементе набор разных слов.
Это - по конкретному вопросу. Но вообще говоря, вам нужна другая структура - скорее граф, потому что если А - синоним Б, то и Б - синоним А. И поиск может идти в любую сторону.
Так что я бы использовал одно из представлений для графов. Синонимичность достаточно небольшое явление, так что граф будет разреженный, а потому я бы использовал что-то типа списков смежности.