代码之家  ›  专栏  ›  技术社区  ›  IRP_HANDLER

另一个命名空间内的C++STD模板专门化[重复]

  •  0
  • IRP_HANDLER  · 技术社区  · 9 月前

    我已经解决了这个问题,它要求我把字谜组合在一起。 因此,对于给定的输入,它应该给出以下输出:

    输入:strs=[“吃”、“茶”、“晒”、“吃”,“nat”,“bat”]

    输出:[[蝙蝠],[nat”,“tan”],[吃了,吃了,茶]]

    我决定使用一个名为 签名 将每个单词的字符频率与简单的哈希算法一起保存

    #include <iostream>
    #include <unordered_map>
    #include <algorithm>
    #include <vector>
    #include <array>
    #include <list>
    #include <string>
    
    template <class T> inline void hash_combine( std::size_t& seed, const T& v ) 
    {
        std::hash<T> hasher;
        seed ^= hasher( v ) + 0x9e3779b9 + ( seed << 6 ) + ( seed >> 2 );
    }
    
    class Signature 
    {
    public:
        void Push( char c ) 
        {
            ++counts[c - 'a']; 
        }
        bool operator==( const Signature& rhs ) const 
        { 
            return counts == rhs.counts; 
        }
        size_t Hash() const 
        {
            size_t hash = 0;
            for( auto v : counts ) 
            {
                hash_combine( hash, v );
            }
    
            return hash;
        }
    
    private:
        std::array<unsigned char, 26> counts = { 0 };
    };
    

    然后我使用这个模板专门化:

    namespace std 
    {
        template <> struct std::hash<Signature> 
        {
            size_t operator()( const Signature& s ) const 
            { 
                return s.Hash(); 
            }
        };
    }
    

    接着是这个 AnagramMap 具有无序签名映射的类

    class AnagramMap 
    {
    public:
        void Push( const Signature& sig, int index ) 
        {
            auto val = map.emplace( sig, std::list{ index } );
            if( !val.second ) 
            {
                val.first->second.emplace_back( index );
            }
        }
        size_t GetSize() 
        { 
            return map.size(); 
        }
        auto begin() 
        { 
            return map.begin(); 
        }
        auto end() 
        { 
            return map.end(); 
        }
    
    private:
        std::unordered_map<Signature, std::list<int>> map;
    };
    

    为了完成这个,the 解决方案 类同时使用 签名 AnagramMap 类来解决问题并返回正确分组的字谜:

    class Solution 
    {
    public:
        std::vector<std::vector<std::string>> groupAnagrams( std::vector<std::string>& strs )
        {
            AnagramMap anagrams;
    
            for( auto i = 0; i < strs.size(); ++i )
            {
                Signature sig;
                for( auto c : strs[i] )
                {
                    sig.Push( c );
                }
    
                anagrams.Push( sig, i );
            }
    
            std::vector<std::vector<std::string>> result;
    
            for( auto& anagram : anagrams )
            {
                auto current_list = anagram.second;
                std::vector<std::string> current_anagram_group;
    
                while( !current_list.empty() )
                {
                    auto current_anagram = strs[current_list.front()];
                    current_list.pop_front();
                    current_anagram_group.emplace_back( current_anagram );
                }
                result.emplace_back( current_anagram_group );
            }
    
            return result;
        }
    };
    

    这一切都很好,但现在我想移动这两个 签名 AnagramMap 将类放入新的命名空间,但不将 解决方案 类,类似这样:

    namespace foo
    {
        class Signature { ... }
        class AnagramMap { ... }
        
    }
    

    有办法做到这一点吗?

    1 回复  |  直到 9 月前
        1
  •  1
  •   3CxEZiVlQ    9 月前

    你不应该专攻 std::hash namespace std 你应该专攻 std::hash 在全局命名空间中。当你使用 struct std::hash 你已经把它专门研究了 命名空间std 对于用户定义的类型。

    自从 Signature 在全局命名空间中,专业化应该是

    // DELETE namespace std 
    // DELETE {
    template <> struct std::hash<Signature> 
    {
        size_t operator()( const Signature& s ) const 
        { 
            return s.Hash(); 
        }
    };
    // DELETE }
    

    https://godbolt.org/z/v46G34GTq -编译良好 namespace foo .