KMP算法以及java代码实现

参考 https://www.cnblogs.com/imzhr/p/9613963.html, 但是这个里面很多图都不见liao

kmp 理论就不介绍了,主要分为两部分:

(1)如何求next数组

next数组就是模式串前缀和后缀的最大公共长度,next[i]表示的是前 i 个字符的最大公共前后缀长度(前后缀都是不包括自身的)

1.next[0]=-1, next[1]=0。
2.在求解next[j]时,令k=next[j-1],
3.比较T[j-1]与T[k]的值,
a. 若T[j-1]等于T[k],则next[j]=k+1。
b. 若T[j-1]不等于T[k],令k=next[k],若k等于-1,则next[j]=0,否则跳至3。

以主串“abcabaabaabcacb” 和模式串 “abaabcac”为例:

模式串T : 

其中next[0] = -1  next [1] = 0 为固定的,也很好想, 当 i = 0 时,前面没有字符,自然为 -1 , 当 i = 1时,前后缀都为空,长度为0

当 i  = 2 时,看的是ab 的前后缀最大公共长度  前缀 : a   后缀 : b   公共长度为0  ,用上面的流程来看

k= next[1] = 0 T[0] 和 T[1] 不相等 所以 k = next[ 0] = -1 next[2] = 0

当 i  = 3 时,k = next [2] = 0 T[0] 和 T[2] 相等 next[3] = k+1 = 1;

当 i  = 4 时,k = next [3] = 1 T[1] 和 T[3] 不相等   k= next[1] = 0   T[0] 和 T[3] 相等  next[4] = k+1 = 1;

当 i  = 5 时,k = next [4] = 1  T[1] 和 T[4] 相等   next[5] = k+1 = 2;

当 i  = 6 时,k = next [5] = 2  T[2] 和 T[5] 不相等   k= next[2] = 0   T[0] 和 T[5] 不相等    k= next[0] = -1  next[6] =0;

当 i  = 7 时,k = next [6] = 0  T[0] 和 T[6] 相等  next[7] = k+1 = 1;

所以next 数组 为

(2)如何利用next数组进行字符串匹配

当主串匹配到第 i 个字符, 模式串T匹配至第 j 个字符时匹配失败,i指针不变,
将j指针置为next[j]的值,若j的值为-1,则将i和j同时加1。随后继续进行逐个的比较。
 

代码实现:

(1)求next 数组

public static void next(String s, int[] next){
        next[0] = -1;
        next[1] = 0;
        for(int i = 2; i < s.length(); i++){
            int k = next[i-1];
            if(s.charAt(k) == s.charAt(i-1)){
                next[i] = k+1;
            }else{
                while(k >= 0 && s.charAt(k) != s.charAt(i-1)){
                    k = next[k];
                    if(k == -1){
                        next[i] = 0;
                    }
                }
                next[i] = k+1;
            }

        }
    }

(2)匹配

 public static int kmp(String s,String p){
        int[] next = new int[p.length()];
        next(p,next);
        int i = 0, j = 0;
        /*
        while(i < s.length() && j < p.length()){
            if(s.charAt(i) == p.charAt(j)){
                i++;
                j++;
            }else{
                j = next[j];
                if(j == -1){
                    i++;
                    j++;
                }
            }
        }
        //这一段是一开始完全按照匹配流程来的 ,   可以改写成下面的
         */
        while(i < s.length() && j < p.length()){
            if(j == -1 || s.charAt(i) == p.charAt(j)){
                i++;
                j++;
            }else{
                j = next[j];
            }
        }
        return j == p.length() ? i-j : -1;
    }
 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值