BP—and—KMP

1.BP(暴力匹配)

 假设我们现在有两个字符串:
 	//文本串
 	String s = "BBC ABCDAB ABCDABCDABDE";
 	//待匹配字符串
 	String p = "ABCDABD";

整个算法的分析过程:

	首先我们需要两个指针用于扫描两个字符串:
	//扫描字符串s
	int i = 0 ;
	//扫描字符串p
	int j = 0 ;

流程如下:
在这里插入图片描述
此时就要进行回退操作:

	i = i - j ;
	j = 0 ; 

在这里插入图片描述
代码如下:

    public static int BP(String s , String p){
        //i----扫描s字符串的指针,j---扫描P字符串的指针
        int j = 0 ;
        for (int i = 0 ; i < s.length() ; i++){
            if (p.charAt(j) == s.charAt(i)){
                if (j == p.length()-1){
                    return i - (p.length()-1);
                }
                j++;
            }else {
                /*
                    回退操作:
                        j回退到第一次匹配成功后的下标
                        i回退到待匹配字符的首字符的下标(0)
                 */
                i = i - j ;
                j = 0 ;
            }
        }
        return -1 ;
    }

2.KMP算法

首先我们来思考一下BP的缺点在什么地方:

 这里我直接指出来,在回退操作中,BP算法直接屏蔽掉了 在当前匹配失败之前匹配成功的字符。
 这使得我们又要重复扫描一些不需要再次扫描的字符。

那么KMP算法怎么回退呢?

(以下图片资源非本人制作)
我们令 i 不变
而 j = next[ j ] ;
这样做我们就吧重复的AB当作已经匹配好的前缀,再继续扫描字符s
现在我们还不知道next数组是什么,接下里你就会明白了
在这里插入图片描述
在这里插入图片描述

接下来我们去研究以下next[ ]数组先,一旦next[ ]我们构建完毕,那么KMP算法写起来就十分简单了。

next[ ]数组的构建和具体含义

next[] 数组的含义 : 前缀与后缀最长的公共字符串的长度
例如:
在这里插入图片描述
实现代码如下:

private static int[] getNext(String p){
        int[] next = new int[p.length()];
        /*
            这里i(慢) j(快)相当于一个快慢指针
         */
        int i = -1, j = 0;
        next[0] = i ;
        while (j < (p.length()-1)){
            if (i == -1 || p.charAt(j) == p.charAt(i)){
                i++;
                j++;
                next[j] = i;
            }else {
                i = next[i];
            }
        }
        System.out.println(Arrays.toString(next));
        return next;
    }

KMP算法—完整代码如下:

	public static int KMP(String s, String p){
        int[] next = getNext(p);
        int i = 0 , j = 0 ;
        while (i < p.length() && j < s.length()){
            if (i == -1 || s.charAt(j) == p.charAt(i)){
                i++;
                j++;
            }else {
                i = next[i];
            }
        }
        if (i == p.length())return j - p.length();
        return -1 ;
    }
    private static int[] getNext(String p){
        int[] next = new int[p.length()];
        /*
            这里i(慢) j(快)相当于一个快慢指针
         */
        int i = -1, j = 0;
        next[0] = i ;
        while (j < (p.length()-1)){
            if (i == -1 || p.charAt(j) == p.charAt(i)){
                i++;
                j++;
                next[j] = i;
            }else {
                i = next[i];
            }
        }
        System.out.println(Arrays.toString(next));
        return next;
    }

KMP算法中i j 的变化如下,会更好的帮助你去理解整个过程。
妙不可言妙不可言
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值