【问题标题】:Why/how does the Longest Proper Prefix/Suffix algorithm work?最长正确前缀/后缀算法为什么/如何工作?
【发布时间】:2020-07-06 06:41:16
【问题描述】:

LPS(Longest Proper Prefix,也是后缀)算法如下:

public static int[] constructLPSArray(String s) {
        int n = s.length();
        int[] arr = new int[n];
        int j = 0;
        for (int i = 1; i < n; ) {
            if (s.charAt(i) == s.charAt(j)) {
                arr[i] = j + 1;
                i++;
                j++;
            } else {
                if (j != 0) {
                    j = arr[j - 1];
                } else {
                    i++;
                }
            }
        }
        return arr;
    }

if (s.charAt(i) == s.charAt(j)) 部分看起来很清晰,但 else 部分不清楚。 我们为什么这样做:

if (j != 0) {
  j = arr[j - 1];
} else {
  i++;
}

更具体地说,为什么j = arr[j - 1] 有效?或者我们为什么要这样做?我们如何验证这一步的正确性?

【问题讨论】:

    标签: arrays algorithm prefix suffix knuth-morris-pratt


    【解决方案1】:

    假设我们正在解析一个字符数组,其中 i 和 j 的位置如下:

    a b a b x x a b a b ...
          ^           ^
          j           i
    

    arr 持有:

    0 0 1 2 0 0 1 2 3 4
    

    我。例如,该长度的 s 的每个子串的最长前缀/后缀的长度,直到i。您可能会猜到它是如何从算法的其余部分生成的。现在,如果i 之后的下一个字符与j 之后的下一个字符不匹配,

    a b a b x x a b a b a ...
            ^           ^
            j           i
    

    我们不必重试匹配,因为我们知道最长的前缀/后缀我们之前的前缀/后缀!查找 arr[j - 1] 得到 2 - 所以我们基本上缓存了此处突出显示的部分的信息

    A B a b x x a b A B a ...
    === ^           === ^
        j               i
    

    完全相同,无需再比较!

    【讨论】:

    • 你能解释一下为什么时间复杂度是 O(n) 而不是 n^2 其中 n 是字符串的长度吗?由于 'j' 可能会在某些循环迭代中递减,它似乎可能是 O(n^2)
    • 它是否需要查找“我们之前的前缀/后缀的最长前缀/后缀”,它只为任何 i 递减一次 j?想知道它的复杂性如何是线性的。
    • @JoeBlack x = # i,j 增加; y = # j 减少; z = # 只有 i 增加了; A = x+y+z = 我们知道 x+z
    【解决方案2】:
      *Here's one more solution*
      int length=str.length();
      int mid=length/2;
      if(length<2){
           System.out.println("-1");
      }
      for(int i=mid;i>=0;i--){
          String prefix=str.substring(0,i);
          String suffix=str.substring(length-i,length);
          if(suffix.equals("") || prefix.equals("")){
                System.out.println("-1");
          }
          if(suffix.equals(prefix)){
              System.out.println(suffix.length());
              break;
          }
          
      }
      
    

    【讨论】:

      猜你喜欢
      • 2017-01-23
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      • 2011-11-16
      相关资源
      最近更新 更多