zoukankan      html  css  js  c++  java
  • KMP

    1.KMP简介

    KMP是一个在字符串str中找一个子串pattern的匹配算法,在BF这种暴力匹配算法的基础上改进的。他是有三个人提出来的,所以用三个人的名字来命名这个算法

    2.KMP解释

    昨天和今天看了好几篇KMP的博客,有个人说的挺好的,坚持下去,就会有柳暗花明的感觉,下面是这位锅锅的博客地址,可以去看看他写的很详细

    http://blog.csdn.net/v_july_v/article/details/7041827

    我这里也说一下我的理解,做个记录

    KMP和BF不同之处在于,i不用回溯到i - j - 1,而j也不用回溯到0这样就提高了算法的效率。

      (1)出现str[i]和pattern[j]不匹配值,i不动,j回溯到next[j](next[]存放的就是匹配失败时,j应该回溯到pattern中的位置)

      (2)str[i]与pattern[j]匹配时,i++,j++

    这里我就不去讨论,为什么j直接跳转到next[j]的位置就okay了。我也不是很理解,这里面有什么前缀后缀,还有些什么之类的...感觉有点懂。其实这里感觉只要理解了怎么计算next[]数组的就okay了

    3.next[]数组的计算

    next[0] = -1这个是定义好的,不用计算

    next[j] = ?呢这个就需要递推关系计算了,如果知道了前next[0,.....j - 1]那计算next[j]就可以看pattern[j] == pattern[k]了(k是pattern中前j个字符串的最大公共子串),
    如果相等,则pattern[j] = k + 1;

    如果不等,则继续寻找更小的k = next[k],在比较pattern[j] == pattern[k]

    可以参考代码,以上解释只为做个记录

     1 package com.gxf.kmp;
     2 
     3 public class KmpSear {
     4     
     5     /**
     6      * 获取next[]的值
     7      * 这里用递推实现
     8      * @param pattern
     9      * @param next
    10      */
    11     public void getNext(String pattern, int next[]){
    12         int k = -1;//最长公共前缀后缀
    13         int j = 0;
    14         next[0] = -1;//第一个字符的next[]值为-1
    15         int length = pattern.length();
    16         
    17         while(j < length - 1){
    18             if(-1 == k || pattern.charAt(j) == pattern.charAt(k)){//如果相同前缀和后缀长度+1
    19                 k++;
    20                 j++;
    21                 if(pattern.charAt(j) == pattern.charAt(k)){//优化过后的,少一次递推
    22                     next[j] = next[k];
    23                 }
    24                 else{
    25                     next[j] = k;
    26                 }
    27             }
    28             else{//如果相同前缀和后缀没有+1,递推找前面最小的相同前缀和后缀
    29                 k = next[k];
    30             }
    31         }
    32     }
    33     
    34     /**
    35      * 匹配字符串
    36      * @param str
    37      * @param pattern
    38      * @return
    39      */
    40     public int kmpSear(String str, String pattern){
    41         int next[] = new int[pattern.length()];//next j的值
    42         getNext(pattern, next);//获取next j的值
    43         showNext(next);
    44         int i = 0;//指向str
    45         int j = 0;//指向pattern
    46         
    47         while(i < str.length() && j < pattern.length()){
    48             if(j == -1 || str.charAt(i) == pattern.charAt(j)){
    49                 j++;
    50                 i++;//如果pattern移动到最开始的位置or两个字符刚好相等,同时移动i和j
    51             }
    52             else{
    53                 j = next[j];//匹配失败,获取下一个j的位置
    54             }
    55         }
    56         if(j == pattern.length()){
    57             return i - pattern.length();
    58         }
    59         return -1;
    60     }
    61     
    62     /**
    63      * 输出next[]的内容
    64      * @param next
    65      */
    66     public void showNext(int next[]){
    67         for(int i = 0; i < next.length; i++){
    68             System.out.print(next[i] + " ");
    69         }
    70         System.out.println();
    71     }
    72     
    73     /**
    74      * 测试程序
    75      * @param args
    76      */
    77     public static void main(String args[]){
    78         KmpSear kmpSear = new KmpSear();
    79         String str = "substring searching algorithm";
    80         String pattern = "search";
    81         int index = kmpSear.kmpSear(str, pattern);
    82         
    83         System.out.println("index = " + index);
    84     }
    85 }
  • 相关阅读:
    mysql MHA报错 Can't exec "mysqlbinlog": No such file or directory at /usr/local/share/perl5/MHA/BinlogManager.pm line 99.
    树莓派搭建私人服务器
    动手写简单的嵌入式操作系统一
    java 返回json数据
    C语言中内存分配
    IntelliJ IDEA14.0.3+Maven+SpringMVC+Spring+Hibernate光速构建Java权限管理系统(三)
    linux设备驱动归纳总结
    阿里云centos6.5下搭建javaWeb运行环境
    JAVAWEB项目如何实现验证码
    Linux驱动开发:USB驱动之usb_skel分析
  • 原文地址:https://www.cnblogs.com/luckygxf/p/4098406.html
Copyright © 2011-2022 走看看