KMP算法

KMP算法

KMP算法主要解决字符串匹配问题,时间复杂度可以达到O(N)

/**
 * kmp算法
 * 
 * 概念:
 *  字符串中每个位置的指标:当前字符之前的字符,前缀和后缀的最长匹配长度
 *  例:abcabck  则k位置的指标为3,前缀最长为abc,后缀最长为abc
 *
 * <p>
 * 解决问题(字符串匹配问题):
 * 两个字符串A、B,A字符串是否包含B字符串
 * 两棵树A、B,B是否和A的某颗子树相同
 *
 * @CreateDate 2020/10/22 16:01
 **/
public class Kmp {

    /**
     * 判断字符串str中,是否存在match字符串,
     * 存在返回第一次匹配的开始位置,不存在返回-1
     *
     * @param str
     * @param match
     * @return
     */
    public int getIndexOf(String str, String match) {
        //如果str为空,或者match为空,或者match的长度>str的长度,则都不存在,返回-1
        if (str == null || match == null || match.length() < 1 || match.length() > str.length()) {
            return -1;
        }
        char[] strCharArray = str.toCharArray();
        char[] matchCharArray = match.toCharArray();
        //str 中当前比对到的位置
        int x = 0;
        //match 中当前比对到的位置
        int y = 0;
        //匹配字符串中,各个字符位置的指标数组
        int[] next = getNextArry(matchCharArray);
        while (x < str.length() && y < match.length()) {
            //如果当前str[x]位置的字符与match[y]当前的字符相等,则x和y同时往前移动
            if (strCharArray[x] == matchCharArray[y]) {
                x++;
                y++;
                //如果当前match的位置已经到第一个位置,则代表str之前的所有位置都没有匹配的,str向后移动一个位置
            } else if (y == 0) {
                x++;
                //否则,y到当前位置的指标位置
            } else {
                y = next[y];
            }
        }
        //最后要么x越界,要么y越界,如果y的值等于match的长度,说明匹配成功,返回x-y即为匹配到的开始位置
        return y == match.length() ? x - y : -1;
    }

    /**
     * 获取匹配字符串中各个位置字符的指标
     *
     * @param match
     * @return
     */
    public int[] getNextArry(char[] match) {
        if (match.length == 1) {
            return new int[]{-1};
        }
        int[] next = new int[match.length];
        //人为规定,第一个位置为-1,第二个位置为0
        next[0] = -1;
        next[1] = 0;
        //当前计算的位置
        int index = 2;
        //cn 代表,cn位置的字符,是当前和i-1位置比较的字符
        int cn = 0;
        while (index < match.length) {
            //如果index-1位置的值和当前cn所在位置的值相等,则index位置的值对应的标准为cn+1,跳出来的时候
            if (match[index - 1] == match[cn]) {
                //next[i] = cn + 1
                //index++ 计算下一个位置的值
                //cn++ 即将面对下一个位置index+1的值,需要用到cn+1
                next[index++] = ++cn;
            } else if (cn > 0) {
                //比对不成功,cn > 0 代表cn还可以往前跳
                cn = next[cn];
            } else {
                next[index++] = 0;
            }
        }
        return next;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值