【问题标题】: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 循环,这将通过在实际排列之前处理初始单词来解决您的问题。
  • @Telescope 谢谢,将其更改为 do while 循环修复了它。从来没有想过使用它,因为我认为当 while 循环通常完成这项工作时它是多余的。我知道这超出了问题的范围,但是您知道为什么二进制搜索与某些单词不匹配吗?它适用于线性搜索,但显然效率要低得多。
  • 二分搜索需要对被搜索的容器进行排序。我猜不是。
  • @JohnFilleau 文本文件包含 25,000 个按字母顺序排列的单词,所以我认为情况并非如此。我已经使用 cout 仔细检查了。

标签: c++ permutation


【解决方案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";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-22
    • 2020-04-10
    • 2013-09-20
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    相关资源
    最近更新 更多