【问题标题】:How map<string, set<string>> is used in this code?这段代码中如何使用 map<string, set<string>> ?
【发布时间】:2013-10-15 09:00:42
【问题描述】:

此代码是此处代码的轻微修改:Given a string array, return all groups of strings that are anagrams
最近1小时看了map、set等文章的参考文献还是看不懂。

   #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";
    }
}

据我了解,set 更像是一个有序向量。所以当我们来到这行代码时

anagrams[sortedWord].insert(word);

它使用我们的 sortedWord 作为键并将该对插入到字谜中。现在,当我继续插入对时,字谜会根据 sortedWord 自动排序。因此,例如,如果我按此顺序插入 cat、god、act,则字谜将包含:

act act
act cat
dgo god

现在,当我使用基于范围的循环时,它会打印这对的第二项。我的理解正确吗? 我有两个问题。当我们使用 sortedWord 作为键时,它为什么不替换之前的值呢?例如,act cat 应该替换 act act。这是因为地图或集合的实施吗?第二个问题,当我尝试为以下输入打印 pair.first 时,我得到了一些随机输出:

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 

如果有人能给我进一步使用 set,我将不胜感激。

【问题讨论】:

  • pair.first 是一个 std::string 所以基于范围的 for 循环告诉你每个字母
  • @SJuan76:std::set 中的顺序并不重要。没有顺序的集合是std::unordered_set

标签: c++ string stl


【解决方案1】:

anagrams[sortedWord].insert(word);

它使用我们的 sortedWord 作为键并将该对插入到字谜中。

不完全正确。 anagrams 是容器,其中每个键都映射到 set。这意味着,anagrams[key] 中可以有很多值,但它们永远不会重复。

考虑输入:cat act dog god none cat,字谜会更像这样:

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

注意,cat 不会重复,doggod 输入都将存储在无意义的 dgo 键下。

当您遍历 pair 的第一个值时,您会得到键,但由于键不是 set,而是 string,因此您会得到单个字符而不是单词。

在我的示例中,您会得到类似 a c t d g o e n n o 的内容,这正是键中的字符。

【讨论】:

    【解决方案2】:

    对于std::map&lt;std::string, std::set&lt;std::string&gt; &gt;,当你这样做时:

    anagrams[sortedWord].insert(word);
    

    它将返回对存储在sortedWord 中的std::set&lt;std::string&gt; 的引用,或者它将(本质上)创建一个新的set 并将其存储在该键中。由于您没有分配 set 给它,set 不会被替换。但在这种情况下,每次您拥有相同的 sortedWord 值时,它都会使用 std::set 上的 insert 方法添加到现有集合中。

    pair.first 的输出而言,它不是随机的。在 map 中,您遍历键和值(键是 first,值是 second)。所以在这种情况下,pair.first 是来自sortedWords 的字符串。所以第一次迭代是act,第二次迭代是dgo。由于您随后遍历了这些字符串对象,因此您将获得各个字符。

    就结构而言,您的地图可以可视化为:

    (key) -> (value - set)  
    act   -> act cat tac  
    dgo   -> dog god  
    

    【讨论】:

    • 谢谢。还有一件事,所以我的字谜的基本结构如下:act cat act tac \newline dgo dog god
    • @user1425223 似乎您的格式混乱或您错过了一次密钥。也许我的插图可以回答你的问题。
    【解决方案3】:

    首先,为什么map&lt;string, set&lt;string&gt; &gt; 中的键不能替换东西? 代码是这样做的:

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

    因此,对于任何单词,它都会首先排序,例如

    act -> act
    cat -> act
    

    并以排序后的版本为键,查找合适的值,即字符串的std::set。未排序的版本word 被插入到集合中。这不会取代之前的内容。
    其次,如果你在一个字符串上使用基于范围的 for 循环,你会得到每个字母。

    【讨论】:

      猜你喜欢
      • 2015-12-05
      • 1970-01-01
      • 2015-11-17
      • 2019-08-26
      • 2019-01-30
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 2018-01-06
      相关资源
      最近更新 更多