刚刚学习了最长公共子串算法,对问题的一个特定变体产生了好奇。它的描述如下:
给定两个非空字符串序列X = (x1, x2, x3,....,x(n))和Y = (y1, y2, y3,..., y(m)),其中x(i)和y(i)是字符的字符串,找到X中在所有Y字符串中都是子串的最长字符串。
我有一个名为substring(x,y) 的函数,它返回布尔值,表示x是否是y的子串。显然,我必须将Y中的所有字符串连接起来形成一个大字符串B。我想到了以下方法:
- Naive: 从连接X中的所有字符串开始,形成一个字符串A(n)。应用substring(A(n),B) - 这包括向后迭代字符串A(n)。如果为真,则算法在此处结束并返回A(n)或包含在所述子字符串中的其任何部分。否则,继续应用(A(n-1),B)等。如果在X中不存在这样的字符串,则返回空字符串。
显然,这种方法取决于实现而需要相当长的运行时间。假设我使用迭代方法,在每次迭代中,我都必须反向遍历该级/索引中的字符串,随后应用substring()。它将至少需要两个循环,并且最坏情况下需要O(size(B)*maxlength(x1,x2,...))的时间,或者更多取决于substring()(如果我错了,请纠正我)。
我想到了一个基于后缀树/数组的第二个方法。
- Generalized Suffix Tree: 使用Ukkonen算法在O(maxlength(y1,y2,...))内构建Y序列的GST。我的后缀树知识不足。我相信后缀树方法会大大减少查找子字符串的运行时间(以空间为代价),但我不知道如何实现该操作。
如果有更好的方法,我很乐意知道。
编辑:如果我使用的不是GST,而是某些标准数据结构,例如堆栈、队列、集合、堆、优先级队列等,会怎样呢?自然地,序列X必须按大小排序,最大的字符串排在前面。如果我将它存储在一个字符串数组中,那么我将必须使用像归并排序/快速排序这样的排序算法。目标是尽可能高效地运行时间。
我能不能将X存储在一个自动排序其元素的结构中?例如最大堆?
在这种情况下,似乎后缀树是以这种方式查找子串的最佳方法。还有其他数据结构可以使用吗?
给定两个非空字符串序列X = (x1, x2, x3,....,x(n))和Y = (y1, y2, y3,..., y(m)),其中x(i)和y(i)是字符的字符串,找到X中在所有Y字符串中都是子串的最长字符串。
我有一个名为substring(x,y) 的函数,它返回布尔值,表示x是否是y的子串。显然,我必须将Y中的所有字符串连接起来形成一个大字符串B。我想到了以下方法:
- Naive: 从连接X中的所有字符串开始,形成一个字符串A(n)。应用substring(A(n),B) - 这包括向后迭代字符串A(n)。如果为真,则算法在此处结束并返回A(n)或包含在所述子字符串中的其任何部分。否则,继续应用(A(n-1),B)等。如果在X中不存在这样的字符串,则返回空字符串。
显然,这种方法取决于实现而需要相当长的运行时间。假设我使用迭代方法,在每次迭代中,我都必须反向遍历该级/索引中的字符串,随后应用substring()。它将至少需要两个循环,并且最坏情况下需要O(size(B)*maxlength(x1,x2,...))的时间,或者更多取决于substring()(如果我错了,请纠正我)。
我想到了一个基于后缀树/数组的第二个方法。
- Generalized Suffix Tree: 使用Ukkonen算法在O(maxlength(y1,y2,...))内构建Y序列的GST。我的后缀树知识不足。我相信后缀树方法会大大减少查找子字符串的运行时间(以空间为代价),但我不知道如何实现该操作。
如果有更好的方法,我很乐意知道。
编辑:如果我使用的不是GST,而是某些标准数据结构,例如堆栈、队列、集合、堆、优先级队列等,会怎样呢?自然地,序列X必须按大小排序,最大的字符串排在前面。如果我将它存储在一个字符串数组中,那么我将必须使用像归并排序/快速排序这样的排序算法。目标是尽可能高效地运行时间。
我能不能将X存储在一个自动排序其元素的结构中?例如最大堆?
在这种情况下,似乎后缀树是以这种方式查找子串的最佳方法。还有其他数据结构可以使用吗?