一个相关的问题叫做Knapsack problem。
这基本上是@Tal Shalti 描述的解决方案。
我试图让所有内容都可读。
我的程序返回 abbcabacac 作为出现次数最多的字符串之一 (3)。
为了获得所有排列而不重复排列,我使用来自algorithm 的std::next_permutation。主要功能中没有发生太多事情。如果实现了更高的出现次数,我只存储出现次数和排列。
int main()
{
std::string word = "abbbaaccca";
std::string patternSmall = "ab";
std::string patternLarge = "aca";
unsigned int bestOccurrence = 0;
std::string bestPermutation = "";
do {
// count and remove occurrence
unsigned int occurrences = FindOccurences(word, patternLarge, patternSmall);
if (occurrences > bestOccurrence) {
bestOccurrence = occurrences;
bestPermutation = word;
std::cout << word << " .. " << occurences << std::endl;
}
} while (std::next_permutation(word.begin(), word.end()));
std::cout << "Best Permutation " << bestPermutation << " with " << bestOccurrence << " occurrences." << std::endl;
return 0;
}
这个函数处理基本算法。 pattern1 是较长的模式,因此将在最后搜索。如果找到一个模式,它将被字符串“@@”替换,因为这在英语中应该是非常罕见的。
变量occurrenceCounter 跟踪发现的出现次数。
unsigned int FindOccurrences(const std::string& word, const std::string& pattern1, const std::string& pattern2)
{
unsigned int occurrenceCounter = 0;
std::string tmpWord(word);
// '-1' makes implementation of while() easier
std::string::size_type i = -1;
i = -1;
while (FindPattern(tmpWord, pattern2, ++i)) {
occurrenceCounter++;
tmpWord.replace(tmpWord.begin() + i, tmpWord.begin() + i + pattern2.size(), "@@");
}
i = -1;
while (FindPattern(tmpWord, pattern1, ++i)) {
occurrenceCounter++;
tmpWord.replace(tmpWord.begin() + i, tmpWord.begin() + i + pattern1.size(), "@@");
}
return occurrenceCounter;
}
此函数返回找到的模式的第一个位置。如果未找到该模式,则std::string::npos 由string.find(...) 返回。同样string.find(...) 开始搜索以索引i 开头的模式。
bool FindPattern(const std::string& word, const std::string& pattern, std::string::size_type& i)
{
std::string::size_type foundPosition = word.find(pattern, i);
if (foundPosition == std::string::npos) {
return false;
}
i = foundPosition;
return true;
}