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));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章