简单压缩方案的最佳运行时间

时间:2018-11-14 15:00:51

标签: algorithm big-o lossless-compression

这是一个简单的难题,在生物信息学中有一些应用。这是某位朋友的工作的抽象版本。

考虑一个非常简单的压缩方案,其输出包含两个操作流:

  • put(a):输出字符a
  • dup():复制到目前为止已写入的所有输出

为方便起见,请为x写一个字符put('x'),为*写一个dup()

例如,"a**b*c"扩展为"aaaabaaaabc"

要压缩给定的字符串s,请找到这两个操作的最短列表以生成它。

例如"aaaaaaaaaab"的缩写为a**a*b。 (a***aab也可以,但要长一个字符。)

我的问题是:最佳压缩的最佳可实现运行时间是什么? (以及实现该运行时的算法是什么。)

我相信线性运行时是可行的,但是我还没有找到比二次方更好的东西。 (不要太担心使用多余的空间。)

1 个答案:

答案 0 :(得分:1)

是的,这种压缩方案可以线性运行。

创建列表dp。对于字符串的前i个元素,此列表的第i个元素将具有最佳的压缩效果。

dp[1] = 1
dp[i] = dp[i-1] + 1
if i is even and first i/2 elements of string are equal to second i/2 elements:
    dp[i] = min(dp[i], dp[i/2] + 1)

要检查第一个i/2元素是否等于第二个i/2元素,您可以找到字符串和后缀之间从索引i/2开始的最长公共前缀。如果此前缀的长度大于或等于i/2,则第一个i/2元素确实等于第二个i/2元素。

使用修改后的LCP阵列可以加快此操作的速度。

首先,为O(n)中的字符串构建一个suffix array

然后,为O(n)中的后缀数组构建一个longest common prefix array

现在,在后缀数组中找到完整字符串的索引。假设它是i。现在,从i迭代到LCP数组的末尾,将每个值替换为到目前为止所看到的最小值。同样,在LCP数组中从i-1向下迭代到0,将每个值替换为到目前为止的最小值。

完成此操作后,LCP数组中的每个值将代表带有完整字符串的后缀的最长公共前缀,这是算法所需的。 请注意,这些值是根据排序后缀而不是字符串中后缀的位置进行排序的。不过,使用后缀数组进行映射非常简单。