4

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]有效?或者我们为什么要这样做?我们如何验证这一步的正确性?

4

2 回答 2

4

假设我们正在解析一个字符数组,其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

完全相同,无需再比较!

于 2020-03-26T15:33:40.390 回答
0
  *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;
      }
      
  }
  
于 2020-09-24T18:19:58.493 回答