【问题标题】:transforming string a to string b将字符串 a 转换为字符串 b
【发布时间】:2013-04-01 05:48:06
【问题描述】:

给定 2 个字符串 AB,您必须通过两个操作将 A 转换为 B

  • delete(i, len):删除从iA开始的len字符(可以不删除字符)
  • insert(i, str):在Ai-th 索引处插入字符串str(可以插入空字符串)

你必须尽量减少删除操作删除的字符数。

约束:

  • insert 只能在删除后应用
  • 删除和插入只能应用一次

示例 1:

A = aabcdef  
B = aaefg

回答:delete(2, 3); insert(4, "g")。总而言之,3个字符被删除,这是我们能做的最好的。

示例2:

A = aaaaa  
B = a

我们只需要删除4个字符

我想到了O(n^3)O(n^2) 的解决方案,但有人告诉我有比这更好的解决方案。

【问题讨论】:

  • 也许已经晚了,但我对要求感到困惑。如果主要性能特征是O(n),其中n是操作数,是不是总是有O(1)的解决方案:删除整个字符串A,然后插入整个字符串B?
  • @angelatlarge 你必须尽量减少删除的字符数

标签: string algorithm optimization data-structures


【解决方案1】:

我想我有一个O(n) 解决方案。它分几个步骤完成。

首先,让我们重新表述问题。我们必须从A 中删除一个子字符串,并从B 中删除一个子字符串,这样剩下的就相等了。我们想从A 中删除作为可能的短子字符串。请注意,您的插入操作实际上等同于对B 的相同删除操作。

引理。如果从AB 中去掉相同的前缀或后缀,则不会影响最佳解决方案。把证据留给读者:)

现在,提取AB 的最大公共后缀和前缀,因此A=XA*YB=XB*Y,其中XY 是子字符串。如果A*B* 为空,我们得到一个简单的退化情况。如果没有,让我们做一个新的符号A<-A*B<-B*

此时first(A) != first(B)last(A) != last(B)。否则,我们应该在上一步中包含一个通用符号作为前缀或后缀:

A = a1 A' a2
B = b1 B' b2

其中a1 = first(A)a2 = last(A)b1 = first(B)b2 = last(B)A'B'AB 的子字符串。这里a1 != b1a2 != b2

要使AB 相等,我们必须从一个字符串中删除第一个符号,从另一个字符串中删除最后一个符号。你这里有两个案例。我们只考虑一个,从A 中删除第一个符号,从B 中删除最后一个符号。

您现在要做的就是从A 的开头删除尽可能少的符号,这样左边的后缀就等于B 的某个前缀。为此,您应该构造字符串Asuffix tree 并遍历B 的所有前缀以检查它们是否出现在后缀树中。然后选择最大的。完成后,你就有了最大的字符串C,即A的后缀和B的前缀:

A = PC
B = CS

A 中删除P 和从B 中删除S,您就完成了。

对于原始的AB(没有删除公共部分),我们有:

A = XPCY
B = XCSY

在问题的原始表述中,P被删除,S被插入。

后缀树可以在O(n) 中构建。在第一步中去掉最常用的后缀和前缀需要O(n)。后缀树遍历在O(n) 中完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-30
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 2022-01-08
    • 2019-10-10
    相关资源
    最近更新 更多