KMP算法

来源:互联网 发布:linux 三个时间 编辑:程序博客网 时间:2024/06/04 11:23

        这几天看了一下KMP算法,这是一个字符串模式匹配的算法。对于初学者来讲,有点难理解。下面就这个算法来看看。

       比如有两个字符串:a b a b a a 

                                       a b a b c a 

       可以看出在第5个字符a和c比较失败了,如果用朴素的比较方法来做,此时应该把下面的字符串右移一位。但是我们并不是这样做的呢?直接将下面的字符串右移两位再来比较,这是为什么呢?因为前面的四位都比较相等,而且前四位又有对称的字符串,长度为2,所以右移两位。

       到目前为止,你可能有一个初步的直观感觉,移动的多少取决于下面字符串的对称长度。而计算这个长度标记为我们常说的next数组。求next数据就是计算字符串的对称长度了,对称长度通过前后缀比较来计算得出。既然要计算对称的长度,那么得要用两个变量来指示了,一个指向前缀,另一个指向后缀,如果相等,就要加1了,这个好理解,如果此时不相等呢?又该回溯多大的距离呢?既然next数组表示的就是回溯的距离,那么此时前缀的变量就等于它的next数组中的值。

      下面是求next数组的算法:

      protected static int[] BuildNext(String P) {//建立模式串P的next[]表
              int[] next = new int[P.length()];//next[]表
              int j = 0;
              int t = next[0] = -1;

             while (j < P.length()-1)
                  if (0 > t || P.charAt(j) == P.charAt(t)) {//匹配
                         j++; t++;
                        next[j] = t;
                 }else//失配
                        t = next[t];
   
                return(next);
     }

     完成KMP算法的代码如下:

     public static int PM(String T, String P) {//KMP算法

  int[] next = BuildNext(P);//构造next[]表

  for(int k=0;k<next.length;k++){

     System.out.print(next[k]+" ");

  }

  int i = 0;//主串指针

  int j = 0;//模式串指针

  while(j< P.length() && i< T.length()) {//自左向右逐个比较字符

    

    if (j< 0 || T.charAt(i) == P.charAt(j)) {//若匹配

      i++; j++;//则转到下一对字符

    } else//否则

      j = next[j];//模式串右移(注意:主串不用回退)

  }//while



  if(j>=P.length())

    return (i-j);

  else return -1;

  }