BF和KMP算法

参考KMP算法
主要是看了上面的讲解,自己做一下记录,加深印象

BF算法

t为目标串,p为模式串
暴力解:思想:先从第一个字符开始匹配,如果p[j]==t[i],那么继续向下比较,一旦不相等,即回溯到目标串的下一个字符,重复工作。

成功条件:当循环结束时,判断j的值与模式串p的长度是否相等,如果相等,说明匹配成功到了模式p的最后一个字符。

返回值:返回模式串在目标串中出现的位置。

方式一:

    public static int bf(String t,String p){
        char[] tchars = t.toCharArray();
        char[] pchars = p.toCharArray();
        int tlen=tchars.length;
        int plen=pchars.length;
        for (int i = 0; i <= tlen-plen; i++) {
            int j;
            for (j = 0; j < plen; j++) {
                if(tchars[i+j]!=pchars[j]){
                    break;
                }
            }
            if(j>=plen){
                return i;
            }
        }
        return -1;
    }

方式二:

    public static int bf1(String t,String p){
        char[] tchars = t.toCharArray();
        char[] pchars = p.toCharArray();
        int tlen=tchars.length;
        int plen=pchars.length;
        int i=0;
        int j=0;
        while (i<tlen&&j<plen){
            if(tchars[i]==pchars[j]){
                i++;
                j++;
            }else {
                i=i-j+1;
                j=0;
            }
        }
        if(j>=plen){
            return i-j;
        }
        return -1;
    }

KMP算法

在这里插入图片描述

公式推出:
利用失效函数进行推,

部分匹配表:
PMT中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。
在这里插入图片描述

由部分匹配表推出next数组:
在这里插入图片描述

代码实现:

    public static int kmp(String t,String p, int[] next){
        char[] tchars = t.toCharArray();
        char[] pchars = p.toCharArray();
        int tlen=tchars.length;
        int plen=pchars.length;
        int i=0;
        int j=0;
        while (i < tlen && j < plen) {
            if (j == -1 || tchars[i] == pchars[j]) {
                i++;
                j++;
            } else {
                j = next[j];
            }
        }
        if(j>=plen){
            return i-j;
        }
        return -1;
    }

核心:如何求取next数组

先给出代码,然后解释为什么这么写;
求解next数组,也就是以模式串p为目标串,找出前面字符串的最长前缀子串;
先理解清楚PMT数组和next数组的关系,PMT数组指的是以当前第i个字符结尾的字符串所拥有的最长前缀子串和最长后缀子串的个数j,也就是第i+1个字符不匹配时,P字符串应该移动到的位置j,继续进行比较;
等同于求解next数组,主要是根据动态规划的思想,假设当前
p0…pk=pj-k…pj;
pmt[j]=k;
若pk+1=pj+1,则pmt[j+1]=k+1=pmt[j]+1;
则对应的next[j+2]=k+1;
对应下面的代码就是当p[i]==p[j]时,说明以i结尾的字符串的最长前缀子串的最后一个字符的下表为j;
则第i+1个字符不匹配的时候,p应该移动的是前面以i结尾的字符串的最长匹配前缀个数j+1,也就是next[i+1]=j+1;也就是对应下面的i++,j++,next[i]=j;

假如p[i]!=p[j],则根据模式串移动的原理,应该继续找第j个字符不匹配时,j应该移动的位置,也就是j=next[j];

以上公式根据教材中的公式,

    public static int[] next(String p) {
        char[] pchars = p.toCharArray();
        int plen = pchars.length;
        int[] next = new int[plen];

        int i = 0;
        int j = -1;
        next[0] = -1;
        while (i < plen - 1) {
            if (j == -1 || pchars[i] == pchars[j]) {
                i++;
                j++;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
        return next;
    }

以上是个人理解的,可以随时交流;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值