在字符串中找到最长的类似子序列

时间:2012-04-01 14:30:01

标签: algorithm data-structures

假设我想找到最长的子序列,使得子序列的前半部分与后半部分相同。

例如:在字符串abkcjadfbck中,结果为abcabc,因为abc在其前半部分和后半部分重复。在搅拌aaa,结果是aa。

2 个答案:

答案 0 :(得分:1)

此任务可能被视为两个众所周知的问题的组合。

  1. 如果你事先知道子序列的两半之间的某个点,你只需找到两个字符串的最佳匹配。这是Pairwise alignment问题。各种动态编程方法在O(N 2 )时间内解决它。
  2. 要找到最佳分割字符串的点,您可以使用Golden section search或Fibonacci搜索。这些算法具有O(log N)时间复杂度。

答案 1 :(得分:0)

在第一次通过inputString时,我们可以计算每个字符出现的频率,并删除出现一个字符的字符。

input: inputString
data strucutres:
Set<Triple<char[], Integer, Integer>> potentialSecondWords;
Map<Char, List<Integer>> lettersList;

for the characters c with increasing index h in inputString do
  if (!lettersList.get(c).isEmpty()) {
    for ((secondWord, currentIndex, maxIndex) in potentialSecondWords) {
       if (there exists a j in lettersList.get(c) between currentIndex and maxIndex) {
         update (secondWord, currentIndex, maxIndex) by adding c to secondWord and replacing currentIndex with j;
       }
    }
    if potentialSecondWords contains a triple whose char[] is equal to c, remove it;  
    put new Triple with value (c,lettersList.get(c).get(0), h-1) into potentialSecondWords;
  }
  lettersList.get(c).add(h);
}
find the largest secondWord in potentialSecondWords and output secondWord twice;

因此,该算法在数组上传递一次,为每个索引创建有意义的三元组,表示从当前索引开始的潜在第二个单词,并更新所有可能的第二个单词。

使用合适的列表实现并且n是inputString的大小,该算法具有最差情况运行时O(n 2),例如,为了^ n。