1

This code is a slight modification of code here: Given a string array, return all groups of strings that are anagrams
I have spent last 1 hour reading references of map, set and other articles but still can't understand it.

   #include <map>
    #include <iostream>
    #include <set>
    #include <algorithm>
    using namespace std;
 int main(){
    int n; cin >>n;
    string word;
    map<string, set<string> > anagrams;
    for (int i=0;i<n;i++){
        cin >> word;
        string sortedWord(word);
        sort(sortedWord.begin(), sortedWord.end());
        anagrams[sortedWord].insert(word);
    }
    for (auto& pair : anagrams){
        for (auto& word: pair.second){
            cout << word << " ";
        }
        //cout << "\n";
    }
}

As I understand set is more of less an ordered vector. So when we come to this line of code

anagrams[sortedWord].insert(word);

It uses our sortedWord as a key and insert the pair into anagrams. Now as I keep on inserting pairs, anagrams is automatically sorted on the basis of sortedWord. So for example, if I insert cat, god , act in this order, anagrams will contain:

act act
act cat
dgo god

Now when I use range based loops, it prints second item of this pair. Is my understanding correct? I have two questions. When we use sortedWord as keys, why doesn't it replace the earlier value? For eg., act cat should replace act act. Is this because of implementation of map or set? And second question, when I try to print pair.first for following input, I get some random output:

Input:
5
cat act dog tac god
Output(for pair.second):
act cat tac dog god
Output(for pair.first):
a c t d g o 

Also I would be grateful if someone could give me further uses of set.

Community
  • 1
  • 1
rishiag
  • 2,248
  • 9
  • 32
  • 57

3 Answers3

3

For std::map<std::string, std::set<std::string> >, when you do this:

anagrams[sortedWord].insert(word);

It will return a reference to the std::set<std::string> stored at sortedWord or it will (essentially) create a new set and store it at that key. Since you are not assigning a set to it, the set is not replaced. But in this case, each time you have the same value for sortedWord, it gets added to the existing set with the insert method on std::set.

As far as the pair.first output, it is not random. In a map, you iterate over both the key and values (key is first, and value is second). So in this case, pair.first is the strings from sortedWords. So the first iteration is act and the second iteration is dgo. Since you then iterate over those string objects, you get the individual characters.

As far as structure, your map could be visualized as:

(key) -> (value - set)  
act   -> act cat tac  
dgo   -> dog god  
crashmstr
  • 28,043
  • 9
  • 61
  • 79
  • Thanks. One more thing, so basically structure of my anagrams is as follows: act cat act tac \newline dgo dog god – rishiag Oct 08 '13 at 12:44
  • @user1425223 it seems either your formatting got messed or you miss a key once. Maybe my illustration in an answer to your question. – sukhmel Oct 08 '13 at 12:48
3

anagrams[sortedWord].insert(word);

It uses our sortedWord as a key and insert the pair into anagrams.

Not quite true. anagrams is container in which every key maps to set. This means, that you can have a lot of values inside of anagrams[key], but they will never be duplicates.

consider input: cat act dog god none cat, anagrams will be more like this:

anagrams-+-act-+-act
         |     +-cat
         |
         +-dgo-+-dog
         |     +-god
         |
         +-enno-+-none

note, that there will be no duplicate of cat, both dog, and god input will be stored under the meaningless dgo key.

When you iterate over first values of pair you get keys, but since key is not set, but string you get individual characters instead of words.

In my example you would get something like a c t d g o e n n o which is exactly characters from keys.

sukhmel
  • 1,402
  • 16
  • 29
1

First, why do the keys in the map<string, set<string> > not replace things? The code does this:

string sortedWord(word);
sort(sortedWord.begin(), sortedWord.end());
anagrams[sortedWord].insert(word);

So, for any word, it is sorted first, e.g.

act -> act
cat -> act

and the sorted version is used as a key, to find the appropriate value, which is a std::set of strings. The unsorted version, word is inserted into the set. This will not replace what was there before.
Secondly, if you use a range based for loop on a string, you will get each letter.

doctorlove
  • 18,872
  • 2
  • 46
  • 62