因为问题陈述不可用,我假设:
- 短语的单词总共必须使用 in 内的总字符,
[]
但不是每个单词都使用[]
.
- 这句话必须完全使用里面的所有字符
[]
- 您可以多次使用单词(可以轻松更新为仅使用一次单词)
- 要使用的单词以小写形式输入。
- 短语中使用的字符以大写形式输入。
代码(在 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