为啥 std::next_permutation 会跳过一些排列?
Posted
技术标签:
【中文标题】为啥 std::next_permutation 会跳过一些排列?【英文标题】:Why is std::next_permutation skipping over some permutations?为什么 std::next_permutation 会跳过一些排列? 【发布时间】:2021-04-24 21:49:52 【问题描述】:“opt”(或这 3 个字母的任意组合)的预期输出应该是“opt”、“top”和“pot”(以任意顺序),但该程序仅查找和匹配“top”和“锅”。 next_permutation 似乎永远不会超过“选择”,我不确定问题是什么。尝试查找“apt”的所有排列时也会出现同样的问题。
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
//int loadDictionary(istream& dictfile, vector<string>& dict);
int permute(string word, vector<string>& dict, vector<string>& results)
std::sort(word.begin(), word.end());
while (next_permutation(word.begin(), word.end()))
cout << "Permutation: " << word << endl;
if (binary_search(dict.begin(), dict.end(), word))
cout << "Match found: " << word << endl;
results.push_back(word);
int matches = results.size();
return matches;
int main()
std::vector<string> dictionary;
std::vector<string> results;
std::string word;
ifstream fileName("words.txt");
cout << loadDictionary(fileName, dictionary);
cout << "\nEnter a string for a anagram: ";
cin >> word;
permute(word, dictionary, results);
cout << "\nMain complete\n";
【问题讨论】:
第 12 行的while (next_permutation(word.begin(), word.end()))
将在循环第一次进入之前对单词 进行置换,这会导致第一个置换丢失。解决此问题的一种方法是将您的 while 循环更改为 do-while 循环,这将通过在实际排列之前处理初始单词来解决您的问题。
见en.cppreference.com/w/cpp/algorithm/next_permutation的例子
@Telescope 谢谢,将其更改为 do while 循环修复了它。从来没有想过使用它,因为我认为当 while 循环通常完成这项工作时它是多余的。我知道这超出了问题的范围,但是您知道为什么二进制搜索与某些单词不匹配吗?它适用于线性搜索,但显然效率要低得多。
二分搜索需要对被搜索的容器进行排序。我猜不是。
@JohnFilleau 文本文件包含 25,000 个按字母顺序排列的单词,所以我认为情况并非如此。我已经使用 cout 仔细检查了。
【参考方案1】:
std::next_permutation
进行排列,所以经常使用do while
:
int permute(std::string word, std::vector<std::string>& dict, std::vector<std::string>& results)
std::sort(word.begin(), word.end());
do
std::cout << "Permutation: " << word << std::endl;
if (std::binary_search(dict.begin(), dict.end(), word))
std::cout << "Match found: " << std::word << std::endl;
results.push_back(word);
while (next_permutation(word.begin(), word.end()));
int matches = results.size();
return matches;
要检查字典,检查所有排列似乎很庞大。
您可以将您的字典转换为“字谜”字典。
std::map<std::string, std::vector<string>> make_anagram_dict(const std::vector<string>& words)
std::map<std::string, std::vector<string>> res;
for (const auto& word : words)
auto anagram = word;
std::sort(anagram.begin(), anagram.end());
res[anagram].push_back(word);
return res;
那么你的主要是
int main()
std::vector<string> words;
ifstream fileName("words.txt");
loadDictionary(fileName, words);
auto dict = make_anagram_dict(words);
do
std::cout << "\nEnter a string for a anagram: ";
std::string anagram;
std::cin >> anagram;
std::sort(anagram.begin(), anagram.end());
auto it = dict.find(anagram);
if (it != dict.end())
for (const auto& word : it->second)
std::cout << "Match found: " << word << std::endl;
while (std::cin); // or other conditions to break the loop
std::cout << "\nMain complete\n";
【讨论】:
以上是关于为啥 std::next_permutation 会跳过一些排列?的主要内容,如果未能解决你的问题,请参考以下文章
将 std::next_permutation 与 2D 数组一起使用
C++ STL应用与实现62: 如何使用std::next_permutation