KMP

···

package newcoder;

public class KMP {
    /**
     * 判断str1中是否有str2,如果有返回在str1中的开始下标
     *
     * @param str1
     * @param str2
     * @return
     */
    public int getIndex(String str1, String str2) {
        char[] c1 = str1.toCharArray();
        char[] c2 = str2.toCharArray();
        int[] next = getNext(c2);
        int i1 = 0, i2 = 0;
        while (i1 < str1.length() && i2 < str2.length()) {
            if (c1[i1] == c2[i2]) {
                i1++;
                i2++;
            } else if (next[i2] == -1) {
                //第一个位置就让i1后移
                i1++;
            } else {
                i2 = next[i2];
            }
        }
        return i2 == str2.length() ? i1 - i2 : -1;
    }

    /**
     * 得到c2的每个元素的前缀和后缀相等的个数
     *
     * @param c2
     * @return
     */
    private int[] getNext(char[] c2) {
        int next[] = new int[c2.length];
        next[0] = -1;
        next[1] = 0;
        int i = 2, cn = 0;//cn当前前缀的长度
        while (i < c2.length) {
            //当前前缀位置的元素等于i-1位置的元素
            //位置前缀就加一,cn加一
            if (c2[cn] == c2[i - 1]) {
                next[i] = cn + 1;
                i++;
                cn++;
            } else {
                //在cn前面继续划分找到和i-1位置匹配的元素,没有就为0
                if (cn > 0) {
                    cn = next[cn];
                } else {
                    next[i++] = 0;
                }
            }
        }
        return next;
    }

    /**
     * 将给出的字符串变成含有两个源字符串的最短字符串
     *
     * @param str
     * @return
     */
    public String getShort(String str) {
        char[] chars = str.toCharArray();
        //计算最长前缀,并且多算一个 然后字符串长度减去最后位置上的前缀长度,就是在末尾添加的字符个数
        int[] next = new int[chars.length + 1];
        next[0] = -1;
        next[1] = 0;
        int i = 2;
        int cn = 0;
        while (i < chars.length + 1) {
            if (chars[i - 1] == chars[cn]) {
                next[i++] = ++cn;
            } else if (cn == 0) {
                i++;
            } else {
                cn = next[cn];
            }
        }
        i = next[chars.length];
        StringBuilder sb = new StringBuilder(str);
        while (i < chars.length) {
            sb.append(chars[i++]);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        KMP kmp = new KMP();
        int n[] = kmp.getNext(new char[]{'a', 'b', 'a', 'b', 'c', 'a', 'b', 'c'});
        int n1[] = kmp.getNext(new char[]{'a', 'a', 'a', 'a', 'a', 'a', 'b', 'c'});
        String s1 = "acbababa", s2 = "ab";
        System.out.println(kmp.getIndex(s1, s2));
        for (int i : n) {
            System.out.println(i);
        }
        System.out.println(kmp.getShort(s1));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值