我写了一个函数,确定两个单词是否是字谜。如果您可以通过重新排列字母来从A构筑B字,那么A字就是B字的字谜,例如:
lead is anagram of deal
这是我的功能:
bool is_anagram(std::string const & s1, std::string const & s2) { auto check = [](std::string const & x) { std::map<char, unsigned> counter; for(auto const & c : x) { auto it = counter.find(c); if(it == counter.end()) counter[c] = 1; else ++counter[c]; } return counter; }; return check(s1) == check(s2); }
这很好用,但是随着单词数量的增加(此功能在我的应用程序中使用了数百万次),很快就成为我应用程序的主要瓶颈。
有谁知道如何加快此功能?
映射的创建以及您std::map::find在迭代中的调用都非常昂贵。
std::map::find
在这种情况下,您可以使用std::string行为在许多方面都类似于 的事实std::vector<char>,这意味着您可以使用对其进行排序std::sort:
std::string
std::vector<char>
std::sort
bool is_anagram(std::string s1, std::string s2) { std::sort(s1.begin(), s1.end()); std::sort(s2.begin(), s2.end()); return s1 == s2; }
而不是您要创建的两个映射,我正在获取字符串的副本(通过值而不是const引用传递它们)并对它们进行排序,因此
sort("lead") => "adel" sort("deal") => "adel"
此更改应该已经使您的算法大大提高了速度。如果您倾向于比较任意单词,则可能会进一步影响性能的一件事:
bool is_anagram(std::string s1, std::string s2) { if(s1.length() != s2.length()) return false; /* as above */ }
如果两个字符串的长度不同,则显然不能为字谜。 std::string::length()这是一个非常快的操作(无论如何,它都需要存储字符串的大小),因此我们免去了O(N*log(N))对两个字符串进行排序的麻烦。
std::string::length()
O(N*log(N))