LCS的蛮力方法及其时间复杂度[O(m * n)!?]

时间:2019-03-17 13:40:52

标签: algorithm time-complexity analysis lcs

我已经阅读了几本算法书籍,被告知最长公共子序列的蛮力方法需要2 ^ n的时间复杂度。而我已经注意到,当我应用蛮力技术时,它消耗的是O(m n)(根据我的个人观察)。 我想请您清楚地阅读我的方法,并在头脑中形象化,并在需要时提出进一步澄清的问题。 我的方法如下:-假设我们有两个字符串 s1 =“ ECDGI”, s2 =“ ABCDEFGHIJ”。 现在,我正在选择给定的字符串之一。可以说s1。 对于i = 1到n( n 是s1的最后一个索引),我采用每个值并将其与s2进行比较,使得对于s1的单个字符,我将检查所有s2的字符。从数学上讲,第i个值将检查所有第j个值,直到m( m 是s2的最后一个索引)。在这里,如果找到任何常用字符,我只需从两个字符串中移至下一个字符。然后只需计算子序列。我通过运行 n 循环来计算s1中每个字符的所有可能子序列。最后,我计算出最大值。 据我了解,这总体上需要O(m n)时间复杂度。 所以我的问题是,“我的时间复杂度计算正确吗?”

踪迹:

i = 1,值= E,lcs = 3 [EGI]

i = 2,值= C,lcs = 4 [CDGI]

i = 3,值= D,lcs = 3 [DGI]

i = 4,值= G,lcs = 2 [GI]

i = 5,值= I,lcs = 1 [I]

答案是= 4(最大lcs)

下面给出了我的代码!

import java.util.*;
public class Main {
      static int count;
      static String s1 = "ECDGI"; // you can try with "EEE" or etc. 
      static String s2 = "ABCDEFGHIJ"; // you can try with "EEE" or etc.
  public static void main(String[] args) {
 LinkedList<Integer> ll = new LinkedList<>();
      for(int i =0; i<s1.length();i++){
      int t = i;
      count = 0; 
       for (int j=0; j<s2.length();j++){
         if(s1.charAt(t)==s2.charAt(j)){
           count++; 
            doIt(t+1,j+1);
            break ; 
        }
       }
        ll.add(count);
      }
      System.out.println(ll); // printing the whole LinkedList
      System.out.println(Collections.max(ll)); // taking the maximum value 
  }
  public static void doIt(int a, int b){
 for ( ; a<s1.length(); a++){
        int t = b ; 
        for (; t<s2.length(); t++){
          if (s1.charAt(a) == s2.charAt(t)){
           count++; 
           b=t+1; 
           break ; 
           }
        }
     }
  }

}

1 个答案:

答案 0 :(得分:1)

  1. 您的算法错误。考虑s1 =“ AABAA”和s2 =“ AAAAB”的情况,您的代码给出3,但LCS为4。

  2. 时间复杂度为O(n * m *(n + m))

    • 为什么?

    • 让我们考虑最坏的情况,其中s1为n / 2'A' 字符和n / 2个“ B”字符,而s2是m / 2个“ A”字符和 m / 2个“ C”字符

    • 现在,如果我们忽略doIt()函数,则循环本身会给出O(n * m)
    • 那么doIt()被调用了多少次?对于s1的所有n / 2个第一个字符对和s2的m / 2个对都很好,所以n / 2 * m / 2次,或者如果我们减去常数O(n * m)次
    • 现在让我们分析doIt()的复杂性
    • 它使用2个指针来传递两个字符串,因此复杂度为O(n + m)
    • 所以总复杂度为O(n * m *(n + m))或O(n ^ 2 * m + m ^ 2 * n)