KMP算法

以下内容是我看尚学堂视频所做的学习笔记
适合曾经学过KMP算法,理解大概原理但是写不出或者不太理解代码的同学,不适合KMP小白。

1. 理论回顾

在这里插入图片描述
在这里插入图片描述

2. java代码实现

2.1 求解next数组

假设已经知道next[y]的取值为len,求next[y+1]的值。

  • P[len] == P[y],则next[y+1] = len + 1 = next[y] + 1
    在这里插入图片描述
  • P[len]≠P[y],则循环地执行len = next[len],直到 len==-1或者满足P[len] == P[y]为止。当t==0时,next[j+1]=1
    在这里插入图片描述
    由此可得以下代码:
//计算next数组
public static int[] getNext(String subStr){
	//1. 定义一个next数组
	int[] next = new int[subStr.length()];
	//2. 设置next数组的第一个元素值为-1
	next[0] = -1;
	//3. 定义两个变量,y表示模式串的索引值,len表示当索引为y时,最长公共前后缀的长度
	int y = 0, len = -1;
	//4. 定义一个循环,用于计算next数组
	while(y < subStr.length()-1){
		//5. 处理len和y指向模式串中的字符相等的情况
		if(len == -1 || subStr.charAt(len) == subStr.charAt(y)){
		    len++;
		    y++;
		    next[y] = len;
		}else{
	        //6. 处理len和y指向模式串中的字符不相等的情况
		    len = next[len];
	    }
	}
	//7. 返回
	return next;
}

2.2 完整代码

import java.util.Arrays;
public class Test {
    
    public static void main(String []args) {
		//主串
		String destStr = "BABABACABABCABAABD";
		//模式串
		String subStr = "ABABCABAAB";
		//测试next数组
		int[] next = getNext(subStr);
		System.out.println(Arrays.toString(next));
		//测试kmp算法
		int index = kmp(destStr, subStr);
		System.out.println(index);
    }
    
    //计算next数组
	public static int[] getNext(String subStr){
	    //1. 定义一个next数组
		int[] next = new int[subStr.length()];
		//2. 设置next数组的第一个元素值为-1
		next[0] = -1;
		//3. 定义两个变量,y表示模式串的索引值,len表示当索引为y时,最长公共前后缀的长度
		int y = 0, len = -1;
		//4. 定义一个循环,用于计算next数组
		while(y < subStr.length()-1){
		    //5. 处理len和y指向模式串中的字符相等的情况
		    if(len == -1 || subStr.charAt(len) == subStr.charAt(y)){
		        len++;
		        y++;
		        next[y] = len;
		    }else{
		        //6. 处理len和y指向模式串中的字符不相等的情况
		        len = next[len];
		    }
		}
		//7. 返回
		return next;
	}

	//实现KMP算法
	public static int kmp(String destStr, String subStr){
		//0. 计算next数组
		int[] next = getNext(subStr);
	    //1. 定义两个变量,分别指向主串和模式串中的第一个字符
	    int x = 0, y = 0;
	    //2. 定义一个循环,用于实现字符串的匹配操作
	    while(x < destStr.length() && y < subStr.length()){
	        if(y == -1 || destStr.charAt(x) == subStr.charAt(y)){
	            //3. 如果相等,则继续比较后续字符
	            x++;
	            y++;
	        }else{
	            //4. 如果不等,则主串指针不动,模式串指针回溯
	            y = next[y];
	        }
	    }
	    //5. 如果模式串遍历结束,则匹配成功,否则失败
	    if(y == subStr.length()) return x - y;
	    else return -1;
	}
}

执行结果:

[-1, 0, 0, 1, 2, 0, 1, 2, 3, 1]
7
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值