zoukankan      html  css  js  c++  java
  • KMP算法实践与简单分析

    一、理解next数组

    1、约定next[0]=-1,
    同时可以假想在sub串的最前面有一个通配符“*”,能够任意匹配。对应实际的代码t<0时的处理情况。

    2、next[j]可以有如下的几种理解思路:
    1)next[j]为sub[j]前面的字符串的前后缀字符串匹配的最大匹配长度
    例如sub=“ababap”
    next[5]=3,前后追匹配字符串为“aba”
    2)在sub[j]位置匹配失败后,next[j]为为sub串的位置指针j能够先前回溯到的位置。
    3)next[j]为最长前缀匹配串的下一个字符位置(这就是为什么求next数组时需要有t=next[t]这一步。)

    由此不难发现:
    next[j]的值越大,在base[i]与sub[j]处匹配失败时,sub串的位置指针j需要回溯的跨越长度越小。
    反之,
    next[j]的值越小,在base[i]与sub[j]处匹配失败时,sub串的位置指针j需要回溯的跨越长度越大。
    极端情况下,next[j]为0,sub串的位置指针j直接回溯到sub串起始位置。

    二、理解KMP主算法

    1、base串的位置指针i在匹配的过程中始终不会向前回溯,这也是KMP算法较蛮力匹配算法高效的原因。
    2、当base[i]和sub[j]匹配失败时,sub串的位置指针j回溯,j变小,等效于将sub串向右移动。

    j回溯到next[j]的位置。

    三、理解改进的next数组

    改进的next数组的取值优化算法:

    if (sub.charAt(t) != sub.charAt(j)) {
        next[j] = t;
    }else{
        next[j] = next[t];
    }

    考虑对于base主串和sub串如下:
    String base = "aaaabcde";
    String sub = "aaaaax";
    用改进的next数组取值为[-1,-1,-1,-1,-1,4]
    当b=base[4] != sub[4]=x时,j=next[j]=-1,直接跳到sub串的哨兵“*”位置,然后进入j<0,进而i++,j++,中间省略了层层回溯的步骤。

    其原理相当于简化了将KMP主算法中的sub位置指针j的跳转条件t = next[t];的负担。
    因为在KMP主算法中base[i] != sub[j]时,j经过第一次回溯之后,如果出现sub[[next[j]]]=sub[j]的话,不难推断sub[[next[j]]]=sub[j]!=base[i],那么这一次回溯是没有实际效果的,j必将还要向前回溯。。。基于这样的考虑,直接对next数组做优化处理,避免了主算法中这样的层层回溯,能够减少主算法中while循环的次数。

    改进的next数组能够避免sub串的位置指针j层层向前回溯,保证每次j的回溯都是有效的。

    四、java实现如下

     1 package agstring;
     2 
     3 public class KMP {
     4     public static int[] getNextAry(String sub){
     5         int subLenght = sub.length();
     6         int[] next = new int[subLenght];
     7         int t = next[0] = -1,j = 0;
     8         while(j < subLenght-1){
     9                 if(t < 0 || sub.charAt(t) == sub.charAt(j)){
    10                     t++;
    11                     j++;
    12                     next[j] = t;//可优化
    13                 }else {
    14                     t = next[t];
    15                 }
    16         }
    17         return next;
    18     }
    19     public static int[] getNextAryExt(String sub){
    20         int subLenght = sub.length();
    21         int[] next = new int[subLenght];
    22         int t = next[0] = -1,j = 0;
    23         while(j < subLenght-1){
    24                 if(t < 0 || sub.charAt(t) == sub.charAt(j)){
    25                     t++;
    26                     j++;
    27                     next[j] = sub.charAt(t) != sub.charAt(j)?t:next[t];
    28                 }else {
    29                     t = next[t];
    30                 }
    31         }
    32         return next;
    33     }
    34 
    35     /*
    36      *i为主串位置指针,j为sub串位置指针
    37      *j<0的情况为sub串的位置指针为0,且sub[0] != base[i]
    38      *匹配能够成功的情况必为j==subLength
    39      * */
    40     public static int  matchOfKMP(String base,String sub){
    41         int baseLength = base.length();
    42         int subLength = sub.length();
    43         int i = 0,j = 0;
    44         int[] next = getNextAryExt(sub);
    45         while(i < baseLength && j < subLength){
    46             if(j < 0 || base.charAt(i) == sub.charAt(j)){
    47                 i++;
    48                 j++;
    49             }else {
    50                 j = next[j];
    51             }
    52         }
    53         int result = j == subLength?i-j:-1;
    54         return result;
    55     }
    56     
    57     public static void main(String[] args) {
    58         try {
    59             String base = "ababghababa";
    60             String sub = "ababap";//chinchilla,ababaaaba,
    61             int result = matchOfKMP(base, sub);
    62             System.out.println(result);
    63         } catch (Exception e) {
    64             // TODO: handle exception
    65             e.printStackTrace();
    66         }
    67     }
    68 }
  • 相关阅读:
    防火墙透明模式
    HP管理工具System Management Homepage安装配置
    kbmmw 中JSON 中使用SQL 查询
    kbmmw 中JSON 操作入门
    第一个kbmmw for Linux 服务器
    kbmmw 5.02发布
    kbmmw 5.01 发布
    使用delphi 10.2 开发linux 上的Daemon
    使用unidac 在linux 上无驱动直接访问MS SQL SERVER
    使用delphi 10.2 开发linux 上的webservice
  • 原文地址:https://www.cnblogs.com/qcblog/p/7499696.html
Copyright © 2011-2022 走看看