【问题标题】:Creating a phrase given a string vector of words in c++在c ++中给定单词的字符串向量创建一个短语
【发布时间】:2014-09-25 17:36:35
【问题描述】:

到目前为止,我的 c++ 程序如下所示:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int i;
    int maxLet;
    const int NumWords = 26;
    const int NumPhrase = 8;
    string ele;
    string n[NumWords] = {
        "crypt",  "by",     "my",     "cysts",  "glyph", "psych", "shyly",
        "slyly",  "try",    "sylph",  "tryst",  "gypsy", "ply",   "pry",
        "shy",    "sly",    "spy",    "thy",    "cry",   "sty",   "glyphs",
        "sylphs", "trysts", "crypts", "psychs", "sprly"};
    vector<string> words(n, n + NumWords);
    vector<string> phrase(n, n + NumPhrase);
    for (i = 0; i < words.size(); i++) {
        cout << words.at(i) << endl;
        cout << words[i] << endl;
    }

    char aaaaa;
    cin >> aaaaa;
    return 0;
}

我需要创建一个类似于 [YYY] [YYYYY] [YYYBC] [GHLLLM] [PPPRR] [RS] [SS] [SSTTT] 其中字母全部打乱,括号表示单词的长度。 本质上,我需要创建一个具有特定单词长度和特定字母数量的词组 总共有, 11 岁 1个 1摄氏度 1克 1小时 3 升 1米 3个 3r的 5秒 3t的 我一直在拔头发,试图弄清楚该怎么做。非常感谢您的意见。

【问题讨论】:

  • 你的程序离解决方案真的太远了,它甚至不包含输入字符串( cin )的有效解析,这将是带有 '['']{ 的字符串,甚至没有轻微的开始一个算法来解决问题……如果问题太大,分成部分,首先尝试只找到给定大小的所有单词,以便能够填充括号,并保留一串未使用的字符。
  • 几个提示,去掉词组中没有使用的字母,或者词组中没有大小的词,尽量以少用的字母开头(例如:b, c, g, h, m那封信)。例如单词by是单词列表中唯一一个带有b且大小为2的单词,它可以用在RSSS占据的位置。如果到达死胡同,通过递归回溯,它可以完成。尝试用之前的检查放一个单词,更新使用的字母并重试,如果到达死胡同,回溯并尝试其他单词。

标签: c++ vector letters phrase


【解决方案1】:

由于问题陈述不可用,我假设:

  1. 短语的单词总数必须使用 [] 内的总字符数,但不是每个单词都使用 [] 内的确切字符数。
  2. 该短语必须使用[] 中的所有字符
  3. 您可以多次使用一个词(可以轻松更新为只使用一次)
  4. 要使用的单词以小写形式输入。
  5. 短语中使用的字符以大写形式输入。

代码(在 GCC 4.9.0 和 C++11 中测试):

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

bool can_use_word(std::vector<long>& chars_in_phrase, const std::string& word) {
    unsigned int idx = 0;
    bool valid = true;
    // Verifing that the word could be used, that no char is used more that the
    // phrase indicate
    // Updating the char use count in place.
    for (; idx < word.size(); idx++) {
        if (chars_in_phrase[word[idx] - 'a'] == 0) {
            valid = false;
            break;
        }

        chars_in_phrase[word[idx] - 'a']--;
    }

    if (!valid) {
        // If invalid revert the char use count as before.
        for (unsigned int idx_revert = 0; idx_revert < idx; idx_revert++) {
            chars_in_phrase[word[idx_revert] - 'a']++;
        }
        return false;
    }
    return true;
}

bool solve_phrase(std::vector<long>& chars_in_phrase,
                  std::vector<long>& phrase_word_length,
                  const std::vector<std::string>& words_to_use,
                  std::vector<std::string>& phrase,
                  unsigned int phrase_word_idx = 0) {
    if (phrase_word_idx == phrase_word_length.size()) {
        // If we reach the last word length of the phrase and no char is left
        // for use, we found our solution.
        bool valid = true;
        for (auto cu : chars_in_phrase) {
            if (cu != 0) {
                valid = false;
                break;
            }
        }
        return valid;
    }

    // Find the first word with the length needed.
    auto it = std::find_if(
        words_to_use.begin(), words_to_use.end(),
        [&phrase_word_length, phrase_word_idx](const std::string& str) {
            return str.size() == phrase_word_length[phrase_word_idx];
        });

    // If not have the length needed (it's not possible in the actual algorithm,
    // because we allow using
    // the same word multiple times, if its only used once, could be necessary).
    if (it == words_to_use.end() ||
        it->size() != phrase_word_length[phrase_word_idx])
        return false;

    // Iterate throught the words with the same target length.
    while (it != words_to_use.end() &&
           it->size() == phrase_word_length[phrase_word_idx]) {
        if (can_use_word(chars_in_phrase, *it)) {
            phrase.push_back(*it);
            // Continue searching the next word in the phrase
            if (solve_phrase(chars_in_phrase, phrase_word_length, words_to_use,
                             phrase, phrase_word_idx + 1))
                return true;
            // If it reach dead end, revert the state of the used chars and
            // continue with the next possible word.
            phrase.pop_back();
            for (unsigned int idx = 0; idx < it->size(); idx++) {
                chars_in_phrase[(*it)[idx] - 'a']++;
            }
        }
        it++;
    }

    return false;
}

int main() {
    std::vector<std::string> words_to_use{
        "crypt",  "by",     "my",     "cysts",  "glyph", "psych", "shyly",
        "slyly",  "try",    "sylph",  "tryst",  "gypsy", "ply",   "pry",
        "shy",    "sly",    "spy",    "thy",    "cry",   "sty",   "glyphs",
        "sylphs", "trysts", "crypts", "psychs", "sprly"};

    std::string phrase =
        "[YYY] [YYYYY] [YYYBC] [GHLLLM] [PPPRR] [RS] [SS] [SSTTT]";
    std::vector<long> chars_in_phrase(26, 0);
    std::vector<long> phrase_word_length;

    // Initializing the char used in the phrase and the word length of the
    // phrase
    unsigned int begin_idx = 0;
    for (unsigned int idx = 0; idx < phrase.size(); idx++) {
        char c = phrase[idx];
        if (c == '[') {
            begin_idx = idx;
        } else if (c == ']') {
            phrase_word_length.push_back(idx - begin_idx - 1);
        } else if (c != ' ') {
            chars_in_phrase[c - 'A']++;
        }
    }

    // Sorting the words by size.
    std::sort(words_to_use.begin(), words_to_use.end(),
              [](const std::string& left, const std::string& right) {
        if (left.size() == right.size())
            return left < right;
        return left.size() < right.size();
    });

    std::vector<std::string> phrase_solved;
    solve_phrase(chars_in_phrase, phrase_word_length, words_to_use,
                 phrase_solved);

    for (auto p : phrase_solved) {
        std::cout << p << " ";
    }
    std::cout << std::endl;

    return 0;
}

获得的输出:pry crypt gypsy trysts shyly by my slyly

【讨论】:

  • 这简直是完美的。我花了大约 30 个小时试图做到这一点。你是程序员吗?
  • 是的,我是一名程序员,这是一个非常奇怪的问题,大多数检查此标签的人都是程序员,出于爱好、职业或两者兼而有之。
  • 好吧,我必须首先将一个超过 10,000 个单词和随机字符的文本文件缩减为这 26 个单词。但无论如何,我真的很感谢你的帮助,我希望我能投票给你,但显然你需要至少 15 个代表才能做到这一点。
  • 你可以检查答案,我猜?很高兴这对您有所帮助。
【解决方案2】:

由于您的所有单词模板([...] 的集合)都是不同的,您只需计算每个此类元素的可能匹配项并将这些数字相乘即可。所以,让我们先写一个这样的函数:

bool isMatch(string templ, string word)
{
sort(templ.begin(), templ.end());
sort(word.begin(), word.end());
return templ==word;
}

long long countMatches(string templ, vector<string> const& dict)
{
long long ret=0;
for(int i = 0; i < dict.size(); i++)
  ret += isMatch(templ, dict[i]);
return ret;
}

long long finalAnswer(vector<string> const& templs, vector<string> const& dict)
{
 long long ans=1;
 for(int i=0; i<templs.size(); i++)
   ans*=countMatches(templs[i], dict);
 return ans;
}

【讨论】:

  • 鉴于这个问题,我认为字母匹配是针对整个句子,而不是针对每个单词的括号(但我没有乔希望我们通过的完整考试的确切文本他的地方)。因为...
  • @philippelhardy 这样的问题让我很高兴我是千里眼:)
  • 如果您根据获得 +1 的事实来计算您的千里眼程度,请注意它来自我,而不是来自乔……他似乎并没有很好地关注他的第一篇文章。
  • 我仍然对您的某些功能在做什么感到有些困惑。你指的 vector const& dict 是什么?这是我已经设置的矢量还是新的?
猜你喜欢
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
相关资源
最近更新 更多