Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 最长正确前缀/后缀算法为何/如何工作?_Arrays_Algorithm_Prefix_Suffix_Knuth Morris Pratt - Fatal编程技术网

Arrays 最长正确前缀/后缀算法为何/如何工作?

Arrays 最长正确前缀/后缀算法为何/如何工作?,arrays,algorithm,prefix,suffix,knuth-morris-pratt,Arrays,Algorithm,Prefix,Suffix,Knuth Morris Pratt,LPS(最长正确前缀,也是后缀)算法如下所示: 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)) {

LPS(最长正确前缀,也是后缀)算法如下所示:

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;
    }

更具体地说,为什么
j=arr[j-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
一,。e、 ,该长度的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
是相同的,不需要再次比较

*这里还有一个解决方案*
  *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;
      }
      
  }
  
int length=str.length(); int mid=长度/2; 如果(长度=0;i--){ 字符串前缀=str.substring(0,i); 字符串后缀=str.substring(长度-i,长度); if(后缀.equals(“”)|前缀.equals(“”){ 系统输出打印项次(“-1”); } if(后缀等于(前缀)){ System.out.println(后缀.length()); 打破 } }
您能解释一下为什么时间复杂度是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 *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; } }