java實現字符串的一般和KMP模式匹配算法

/**
 * Created by on 2017/8/20.
 */
public class StringIndex {
    public static void main(String agrs[]){
        String s = "dsadaaaabdad";
        String t = "aaaab";
//        int pos = BFIndex(s,t);
        int pos = KMP(s,t);
        System.out.println(pos);

        int[] next = new int[t.length()];
        get_next(t,next);
        for (int i = 0; i < next.length; i++) {
            System.out.print(next[i]+" ");
        }
    }

    /**
     * 字符串的一般模式匹配算法
     * @param s 主串
     * @param t 子串
     * @return 子串在主串的下標
     * 時間複雜度:O(n+m) 最壞O(n*m)
     */
    public static int BFIndex(String s,String t){
        int i = 0,j = 0;
        while (i < s.length() && j < t.length()){
            if (s.charAt(i) == t.charAt(j)){
                i++;
                j++;
            }else {
                i = i - j + 1;
                j = 0;
            }
        }
        if (j >= t.length()){
            return i - t.length();
        }else {
            return -1;
        }
    }

    public static int KMP(String s,String t){
        int i = 0,j = 0;
        int next[] = new int[t.length()];
        //獲得next數組
        get_nextval(t,next);
        //開始匹配
        while (i < s.length() && j < t.length()){
            if (j == 0 || s.charAt(i) == t.charAt(j)){
                //相等就繼續
                i++;
                j++;
            }else {
                //否則主串位置不變,子串位置 j = next[j]
                j = next[j];
            }
        }
        if (j >= t.length()){
            //子串匹配完返回子串所在主串下標
            return i - t.length();
        }else {
            return -1;
        }
    }

    /**
     * 求解KMP算法的next數組
     * 前兩位必爲0,1。
     * 後面根據前一位進行比較得到:
     *next[j]前一位與其next[j]值對應的內容進行比較,如果相等,next[j+1] = next[j]+1(在java中需要-1 = next[j]+0);
     * 如果不等,繼續向前尋找next[j-1]值對應的內容來與前一位nex[j-1]進行比較,依次比較[j-2...]和它值對應的內容,直到相等。
     * 如果到第一位都不相等則next[j+1]=1(在java中需要-1 = 0)。其中j爲下標
     *
     * @param next
     */
    public static void get_next(String t , int next[]){
        int i = 0,j = -1;
        next[0] = -1; //java中第一位爲-1
        while (i < t.length()-1){
            if (j == -1){ //如果到第一位都不相等則next[j+1]=0
                next[++i] = 0;
                j = 0;
            }
            if (t.charAt(i) == t.charAt(j)){
                //確定next[i+1] next[i+1] = next[i] + 1
                //因爲前面j = next[j] = next[i],++j = next[i] + 1 = next[++i] = next[i+1]
                next[++i] = ++j;
            }else {
                j = next[j];//向前尋找下一位next
            }
        }

    }

    public static void get_nextval(String t,int nextval[]){
        int i = 0,j = -1;
        nextval[0] = -1;
        while (i < t.length()-1){
            if (j == -1){ //如果到第一位都不相等則next[j+1]=0
                nextval[++i] = 0;
                j = 0;
            }
            if (t.charAt(i) == t.charAt(j)){
                i++;
                j++;
                if (t.charAt(i) == t.charAt(j)){
                    //如果匹配的一個位置的下一位位置也匹配,則next[i+1]與當前next[i]相等
                    nextval[i] = nextval[j];//相當於nextval[i+1] = nextval[i]
                }else {
                    nextval[i] = j;
                }

            }else {
                j = nextval[j];
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章