寻找最长的重复子序列


9

给定字符串,我想找到最长的重复(至少两次)子序列。也就是说,我想找到一个字符串,它是的子序列(不一定是连续的),使得。也就是说,是一个字符串,其一半连续出现两次。请注意,是的子序列,但不一定是子字符串。swsw=wwwws

例子:

对于“ ababccabdc”,它将是“ abcabc”,因为“ abc” =“ abc”和“ abc”在“ ababccabdc”中(至少)出现了两次(至少)。

对于“ addbacddabcd”,一个选项为“ dddd”,因为“ dd”出现两次(我不能多次使用相同的字母,但是这里我有4个“ d”,所以还可以),但其值为4。我可以找到更好的一个长度8:“ abcdabcd”,因为“ abcd”是“ addbacddabcd”的子字符串,该子字符串出现两次。

我有兴趣找到最长的重复子序列。这也称为“找到最长/最大的平方”,但我读过许多文章,其中为子字符串而不是子序列定义了平方。

我可以轻松地使用蛮力算法,该算法通过迭代字符串中的断点的所有选项来获取,然后我将在两个字符串中寻找最大/最长的公共子序列,但是使用动态编程技术每次检查将花费,因此整个时间将是。我发现了最长公共子序列更有效的算法,该算法采用,因此运行时间将为。O(n3)O(n2)O(n3)O(n2logn)O(n3logn)

我正在寻找一种更有效的算法来解决最长重复子序列问题。也许我对所有断点进行迭代的想法浪费了太多时间,并且可以减少为更少的迭代。或者也许以不同的态度解决这个问题。

我搜索了许多期刊和以前的问题,发现的大多数结果都与子字符串有关,而不是与子序列有关。

我还读到可以使用后缀树来完成此操作,但这也与子字符串有关,我不确定是否可以将这种想法扩展到子序列。

我正在寻找可以在时间中运行的解决方案。如果在时间上存在一个会更好(我不确定是否存在)。O(n2)O(nlogn)


4
查找后缀树或后缀数组。
别名

1
不可能存在一个时间算法来解决此问题,因为如果确实存在,则可以用它击败最著名的算法来找到两个长度为字符串和的LCS,如下所示:形成字符串,其中是或中都没有出现的字符的副本,然后在其上运行 -time算法。最长重复子序列的两个“一半”都必须以开头,因此一半来自和每个o(n2)nuvxuxvxn+1$uvo(n2)xuv,解决了LCS问题。
j_random_hacker

@j_random_hacker LCS可以使用后缀树在或使用滚动哈希在求解。O(n+m)O(nlogn)
Evil

@Evil:我还不知道如何,您能提供更多细节吗?(您确定您不考虑最长的公共子字符串,可以解决那些时间复杂的问题吗?)
j_random_hacker

@j_random_hacker我以为您正在将目标与LCS(连续)进行比较,但是,正如您提到的,是的,我什至没有在n ^ 2中看到最长公共子序列的有效解决方案(我发现了一种动态的编程代码,传播到许多页面上,存在缺陷,类似于不合格的答案)。因此,很抱歉我误解了您的评论。o(n2)
Evil

Answers:


-1

这是一个动态编程解决方案。

假设输入字符串是。创建一个表其行和列的索引为(其中是字符串的长度),并由规则 答案是。x1xnT0,,nn

T[i,j]={0if i=0 or j=0,T[i1,j1]+1if xi=xj and ij,max(T[i1,j],T[i,j1])otherwise.
T[n,n]

假设我们有一些与,并在条件语句为真。然后暗示位置处的字符是两个子序列的一部分。i,ji=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1i1=j
j_random_hacker '16

3
欢迎来到计算机科学!请删除源代码,并用想法,伪代码和正确性参数替换它。有关相关元讨论,请参见此处此处
拉斐尔

@Raphael递归公式不算作源代码。
Number945 '16

1
@BreakingBenjamin根据您选择的语言,您可以或多或少从字面上写下给定的复发。关键是这里没有解释。
拉斐尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.