嗨,这是我在面试中被要求用C / C ++编写代码的问题。
给定一个字符串,您将获得可能的操作。 我们可以对相邻的子串进行分组,例如ABCABCBC可以压缩为 2ABC1BC或1ABCA2BC
在所有可能的选项中,任务是找到具有最小长度的结果字符串。
如果有多个解决方案,则返回按字典顺序排列的最小字符串。 因此对于上面的例子,解决方案是2ABC1BC
另一个例子是 FLFLAFLAFLAF 解决方案:1FLF3LAF
我知道可以使用后缀树或置换/递归方法来完成,但无法获得如何使用的逻辑。请帮帮忙?
答案 0 :(得分:0)
压缩输入前缀并在输入的其余部分递归调用自身的算法可以做到(live demo):
#include <iostream>
#include <string>
#include <limits>
#include <cstring>
using namespace std;
// determine how many times the prefix of specific length is repeated in the input
int repetitions(string const & input, int prefix_length)
{
int i = 1;
while (
(i + 1) * prefix_length <= input.size() &&
memcmp(input.data(), input.data() + i * prefix_length, prefix_length) == 0
)
{
++i;
}
return i;
}
// recursively compress input and return compressed string
string compress(string const & input)
{
// recursion termination
if (input.empty())
return string();
string best;
int best_length = numeric_limits<int>::max();
// try various prefix lengths
for (int prefix_length = 1; prefix_length <= input.length(); ++prefix_length)
{
const auto max_count = repetitions(input, prefix_length);
// try various number of repetitions up to the maximum possible
for (int count = 1; count <= max_count; ++count)
{
// the candidate is compressed prefix and the rest of input compressed recursively
const auto current =
to_string(count) + input.substr(0, prefix_length) + // compressed prefix
compress(input.substr(prefix_length * count)); // the rest of input compressed recursively
// store candidate if it is better than the currently best
if (current.length() < best_length)
{
best = current;
best_length = current.length();
}
}
}
return best;
}
int main()
{
string input;
cin >> input;
cout << compress(input);
return 0;
}
请注意,这只是一个简单易用的解决方案。它效率不高,并且在长输入时会出现堆栈溢出。