【发布时间】:2013-10-03 11:27:43
【问题描述】:
刚刚学习了最长公共子串算法,我对这个问题的一个特定变体很好奇。描述如下-:
给定两个非空字符串序列,X = (x1, x2, x3,....,x(n)) 和 Y = (y1, y2, y3,..., y(m)) ,其中 x(i) 和 y(i) 是字符串,在 X 中找到 最长 字符串,它是 Y 的 all 字符串的子字符串。
我有一个函数substring(x, y),它返回描述 x 是否是 y 中的子字符串的布尔值。显然,我必须将 Y 中的所有字符串连接起来形成一个大字符串,例如,用 B 表示。我想到了以下方法-:
- 朴素:首先将 X 中的所有字符串连接起来形成一个字符串 A(n)。应用 substring(A(n), B) - 这包括在字符串 A(n) 中向后迭代。如果为真,则算法在此处结束并返回 A(n) - 或包含在所述子字符串中的任何部分。如果不是,则继续申请 (A(n - 1), B) 等等。如果 X 中不存在这样的字符串,则返回空字符串。
显然,这种方法会占用相当多的运行时间,具体取决于实现。假设我使用迭代方法,在每次迭代中,我必须在该级别/索引处向后迭代字符串,然后应用 substring()。这将需要至少两个循环和O(size(B) * maxlength(x1, x2,...)) 最坏情况时间,或者更多取决于 substring() (如果错误,请纠正我)。
我想到了基于后缀树/数组的第二种方法。
-
广义后缀树:我在
O(maxlength(y1, y2,...)(?) 中使用 Ukkonen 算法构建了序列 Y 的 GST。我对后缀树咬伤的知识缺乏。我相信后缀树方法会大大减少查找子字符串的运行时间(以空间为代价),但我不知道如何实现该操作。
如果有更好的方法,我很想知道。
编辑:抱歉,如果我似乎放弃了这个话题。
如果我不使用 GST,而是使用一些标准数据结构,例如堆栈、队列、集合、堆、优先级队列等,会怎样?必须对序列 X 进行排序,首先是最大的字符串。如果我将它存储在一个字符串数组中,我将不得不使用诸如mergesort/quicksort之类的排序算法。目标是尽可能获得最有效的运行时间。
我不能将 X 存储在一个结构中,当它自己构建时,它会自动对其元素进行排序?那么最大堆呢?
后缀树似乎是以这种方式查找子字符串的最佳方式。还有其他我可以使用的数据结构吗?
【问题讨论】:
-
你想要一个字符串,它是 Y 中所有字符串的子字符串。但 B 是所有字符串的并集(不是交集)。因此,您将找到作为 Y 中至少 1 个字符串的子字符串的字符串。我错过了什么吗?
-
m 个字符串的子串不一定是这 m 个字符串之一的子串。因此以下陈述是错误的:“显然,我必须连接 Y 中的所有字符串以形成一个大字符串,例如,用 B 表示。”
-
Y 是一个字符串序列。那我不应该寻找所有字符串的联合/连接吗?这就是我在阅读“Y 中的所有字符串”时所想的。我可能把这搞砸了。可以举个例子解释一下吗?
标签: string algorithm data-structures