您提到当输入字符串长度很大时,您当前的代码太慢了。如果您可以提供一个具体的示例以及您的时间信息,这将很有帮助,这样我们就知道您认为什么“太慢”了。您还应该指定您认为可接受的运行时间。这是一个例子:
我将从一个我认为与您当前算法相似的初始版本开始。它生成所有长度 >= 2 的子序列:
#include <iostream>
#include <string>
void subsequences(const std::string& prefix, const std::string& suffix)
{
if (prefix.length() >= 2)
std::cout << prefix << std::endl;
for (size_t i=0; i < suffix.length(); ++i)
subsequences(prefix + suffix[i], suffix.substr(i + 1));
}
int main(int argc, char* argv[])
{
subsequences("", "ABCD");
}
运行此程序会产生以下输出:
AB
ABC
ABCD
ABD
AC
ACD
AD
BC
BCD
BD
CD
现在让我们将输入字符串更改为更长的内容。我将使用 26 个字符的输入字符串:
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
这会生成 67,108,837 个子序列。我不会在这里列出它们:-)。在我的机器上,上面显示的代码使用 26 个字符的输入字符串运行(不包括输出到 cout)只需要 78 秒多一点。
当我寻找优化上述代码的方法时,跳出来的一件事是它为每个对 subsequences() 的递归调用创建了两个新的字符串对象。如果我们可以预先分配空间然后简单地传递指针会怎样?版本 2:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
void subsequences(char* prefix, int prefixLength, const char* suffix)
{
if (prefixLength >= 2)
printf("%s\n", prefix);
for (size_t i=0; i < strlen(suffix); ++i) {
prefix[prefixLength] = suffix[i];
prefix[prefixLength + 1] = '\0';
subsequences(prefix, prefixLength + 1, suffix + i + 1);
}
}
int main(int argc, char* argv[])
{
const char *inputString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *prefix = (char*) _malloca(strlen(inputString) + 1);
subsequences(prefix, 0, inputString);
}
这会生成相同的 67,108,837 个子序列,但现在执行时间刚刚超过 2 秒(同样,不包括通过 printf 的输出)。