• 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 }
  • 相关阅读:
    SERVER2008下安装SQL SERVER 2005出现IIS功能要求 警告解决方案
    转:Windows Server 2008 IIS 7.0 图文安装详解
    (转)程序集System.Web.DataVisualization无法加载的解决方法
    C++ Primer Plus 读书笔记(第1, 2章)
    寒假就这样来了
    C++ Primer Plus 读书笔记(第8、9章)
    C++ Primer Plus 读书笔记(第6、7章)
    POJ1947 Rebuilding Roads 树形DP
    C++ Primer Plus 读书笔记(第4、5章)
    POJ2754 Similarity of necklaces 2 区间取下界操作+DP
  • 原文地址:https://www.cnblogs.com/qcblog/p/7499696.html
Copyright © 2020-2023  润新知