五、字符串_02 &字符串匹配 &KMP(笔记)

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;

public class A026_字符串匹配_KMP {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.next();
		String s = sc.next();
		int[] next = new int[s.length()];
		f(next, s);
		System.out.println(Arrays.toString(next));
		int i = 0;
		int j = 0;
		while (i < str.length()) {
			if (j < 0 || str.charAt(i) == s.charAt(j)) {
				j++;
				i++;
				if (j == s.length()) {
					System.out.println(i - j);
					j = next[j - 1];
					i--;
				}
			} else {
				j = next[j];
			}
		}
	}

	public static void f(int[] next, String s) {
		next[0] = -1;
		next[1] = 0;
		char[] c = s.toCharArray();
		int j = 1;
		int k = next[j];
		while (j < c.length - 1) {
			if (k < 0 || c[j] == c[k]) {
				next[++j] = ++k;
			} else {
				k = next[k];
			}
		}
	}
}

KMP分两步:
第一步是求next数组,第二步是与原串进行匹配;

一、求next数组

首先看下表👇要求的串的next数组👉bababb

下标 j值 k式子
b0-1next[1] = -1 +1
ba10next[2] = -1 + 1
bab20next[3] = 0 + 1
baba31next[4] = 1 + 1
babab42next[5] = 2 + 1
bababb53/
  • 首先解释最左边的那一列,我们不是建了个数组嘛,其实只要看每行最后一个值就好了,也就是加粗的那些,在进行next数组的求值中,只要比较这些就行。
  • 下标这一列想必不用解释,它不会回退,只会前进,但要注意的是while循环的下标i是到len-1为止,这也是式子中的最后一行是“/”的原因,但是这个位置是会有值的,这个在之后式子这一列说。
  • 值 这一列很奇特,k既是next数组的值,又是下标,感觉这里有点类似于动态规划。
  • 式子这一列中,我们首先固定两个值,分别是next数组下标为0和1的位置,值分别是-1和0,为什么是-1呢?这个到下一步main函数的while里说明
  • 接着说next数组的创建,如果下标k和下标j所对应的c数组中的值相等,那么就将之前的k的值++那么对应的,我们看第一第二行,第一个是b,第二个是a,这两个是不想等的,那么就执行else里面的k = next[k];那么k现在的值就是-1了,那么再进行while循环,这时候,因为k<0,那就会进到if里面,这时候,j变成了2,然后它的值就是0,因为-1±1;
  • 当j=2时,也就是延续上面的走下来,k这个时候是0,但是b和bab,这两个的末位是相等的,那么就将next数组下标为3的这个值,变为++k,也就是1,对应上表,那么接下来也是以此类推,值得注意的就是,他每一次算的,都是下一个下标的值,所以这里会看到,式子这一列的最后一行是空的,但是是有值的。
  • 这样next数组就创建完了,那么接下去就进入主函数了👇

二、进行匹配

  • 首先就是两个下标了i和j
  • 然后这里的i是不会往回走的,只会向前,j的值呢,就是j=next[j],但是这里是什么意思呢?j一直是下标,没变,取出来的值也是下标,这里下标的含义就是说:匹配到这个值的前面,哪个下标是已经相等的了,不用再走的了,比如这里的匹配串中的重复值,就是bababb bababb注意我加粗的两个部分,这两个就是重复的,也就是说,这两个串不用进行比较,下次直接从j的下标3开始比较即可。
  • 那么我们不是有个下标是-1嘛,我们再看原串,在下标为7的位置,有个c,那么走到这里的话,j的下标就是-1了,因为两个元素不相等,我们也可以把所有走的i和j都打印出来看👇,看下面第三个箭头指得位置
    在这里插入图片描述
    那么前两个箭头得值为什么是从大到小的呢?明明没有i变小的地方呀,其实这里,就是next数组的功劳了,j = next[j];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值