简单压缩方案的最佳运行时间
Optimal runtime for simple compression scheme
这是一个简单的谜题,在生物信息学中有一些应用。这是朋友工作中出现的一些抽象版本。
考虑一个非常简单的压缩方案,其输出由两个操作组成:
put(a)
:输出一个字符a
dup()
: 复制到目前为止写入的所有输出
为了记法方便,put('x')
写成字符x
,dup()
写成*
。
例如,"a**b*c"
扩展为 "aaaabaaaabc"
。
要压缩给定的字符串s
,找到这两个操作的最短列表来生成它。
例如 "aaaaaaaaaab"
缩短为 a**a*b
。 (a***aab
也是可以的,但要长一个字符。)
我的问题是:最佳压缩的最佳可实现运行时间是多少? (实现该运行时的算法是什么。)
我相信线性运行时间是可能的,但我还没有发现任何比二次运行时间更好的东西。 (不太担心使用额外的 space。)
是的,线性 运行 时间对于此压缩方案是可能的。
创建列表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 数组中的每个值代表该后缀的最长公共前缀和完整的字符串,这就是算法所需要的。
请注意,这些值是根据排序的后缀而不是后缀在字符串中的位置排序的。不过使用后缀数组映射它相当简单。
这是一个简单的谜题,在生物信息学中有一些应用。这是朋友工作中出现的一些抽象版本。
考虑一个非常简单的压缩方案,其输出由两个操作组成:
put(a)
:输出一个字符a
dup()
: 复制到目前为止写入的所有输出
为了记法方便,put('x')
写成字符x
,dup()
写成*
。
例如,"a**b*c"
扩展为 "aaaabaaaabc"
。
要压缩给定的字符串s
,找到这两个操作的最短列表来生成它。
例如 "aaaaaaaaaab"
缩短为 a**a*b
。 (a***aab
也是可以的,但要长一个字符。)
我的问题是:最佳压缩的最佳可实现运行时间是多少? (实现该运行时的算法是什么。)
我相信线性运行时间是可能的,但我还没有发现任何比二次运行时间更好的东西。 (不太担心使用额外的 space。)
是的,线性 运行 时间对于此压缩方案是可能的。
创建列表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 数组中的每个值代表该后缀的最长公共前缀和完整的字符串,这就是算法所需要的。 请注意,这些值是根据排序的后缀而不是后缀在字符串中的位置排序的。不过使用后缀数组映射它相当简单。