Java实现KMP代码

左神第12节课:
基础提升:有序表、并查集

BM算法:

实际的软件开发中,大部分情况下,模式串和主串的长度都不会太长。而且每次模式串与主串中的子串匹配的时候,当中途遇到不能匹配的字符的时候,就可以就停止了,不需要把 m 个字符都比对一下。所以,尽管理论上的最坏情况时间复杂度是 O(n*m),但是,统计意义上,大部分情况下,算法执行效率要比这个高很多。

https://zh.wikipedia.org/wiki/KISS%E5%8E%9F%E5%88%99

KMP算法是由一个问题而引发的:

对于一个字符串str(长度为N)和另一个字符串match(长度为M),如果match是str的子串,请返回其在str第一次出现时的首字母下标,若match不是str的子串则返回-1。

public class KMP {
    public static void main(String[] args) {
        System.out.println(getIndexOf("abcacb", "cb"));
    }


    public static int getIndexOf(String str, String m) {
        if (str == null || m == null || m.length() < 1 || str.length() < m.length())
            return -1;

        char[] chs1 = str.toCharArray();
        char[] chs2 = m.toCharArray();
        if (chs1.length < chs2.length) return -1;
        int[] next = getNextArr(chs2);

        int i1 = 0, i2 = 0;

        while (i1 < str.length() && i2 < m.length()) {
            //正常匹配的就一个一个向着后面走
            if (chs1[i1] == chs2[i2]) {
                i1++;
                i2++;
                //如果当前的指针指向最后一个的时候,说明i1当前位置与i2所有可能的快速方法都不匹配
            } else if (next[i2] == -1) {
                i1++;
                //当前不ok,那么尝试去看看下一个next数组总的结点但是否可行
            } else {
                i2 = next[i2];
            }
            System.out.println(1);
        }

        return i2 == m.length() ? i1 - i2 : -1;
    }

    public static int[] getNextArr(char[] ms) {
        if (ms.length == 1) return new int[]{-1};
        int[] next = new int[ms.length];
        next[0] = -1;
        next[1] = 0;
        int i = 2;
        int cn = 0;
        // 保证i没有越界
        while (i < ms.length) {
//            i位置的都基于前面的数据
            if (ms[i - 1] == ms[cn]) {
                next[i++] = ++cn;
//          只有cn > 0的时候才能够继续向着前面不停遍历
            } else if (cn > 0) {
                cn = next[cn];
//            遍历到cn也等于0了,没办法了,就直接将这个点的数据设置为0
            } else {
                next[i++] = 0;
            }
        }
        return next;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

willorn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值