1. 程式人生 > >演算法 - KMP演算法

演算法 - KMP演算法

package com.mzs.testThread1;

public class TestDemo {
    /**
     * KMP核心:獲取next陣列,(本方法為其中的一種)
     * 陣列的每個元素是從0位到該元素下標位的最大字首字尾的字串長度
     * @param str 模式字串
     * @return next陣列
     */
	private static int[] getNextArray(String str) {
        char[] array = str.toCharArray();   // 定義模式字串陣列
        int[] nextArray = new int[str.length()];    // 定義next陣列
        nextArray[0] = 0;   // 設定next陣列第一個元素為0(數學邏輯:必須為0)
        int tOrder = 1;    // 從下標為1開始計算陣列元素值
        int maxPreSuf = 0;  // 字首字尾字串相同時的最大長度,(其實就是模式字串匹配的長度)
        while (tOrder < str.length()) {
            while (maxPreSuf > 0 && array[maxPreSuf] != array[tOrder])  // (maxPreSuf沒在起始位置,且失配時)
            	maxPreSuf = nextArray[maxPreSuf - 1];	// (演算法核心):回溯到索引為上一個最大字首字尾長度的next陣列元素值處
            if (array[maxPreSuf] == array[tOrder]) // 匹配時
                maxPreSuf++; 
            nextArray[tOrder] = maxPreSuf;	// 模式字串陣列從0到tOrder,這個字串的匹配的長度也就是next陣列的元素值
            tOrder++;
        }
        return nextArray;
    }
 
    /**
     * KMP演算法
     * @param str 主字串
     * @param str1 模式字串
     */
    private static void getKMP(String str, String str1) {
        char[] array = str.toCharArray();   // 主字元陣列
        char[] array1 = str1.toCharArray(); // 模式字元陣列
        int[] nextArray = getNextArray(str1);    // 獲取模式字串的next陣列
        int sOrder = 0; // 模式字元陣列起始下標,(也就是模式字串匹配的長度)
        for (int i = 0; i < str.length(); i++) {
            while (sOrder > 0 && array[i] != array1[sOrder]) // 下標沒在初始位置,且失配時
            	sOrder = nextArray[sOrder - 1];	// 回溯到索引為上一個sOrder的next陣列的位置處
            if (array[i] == array1[sOrder]) // 匹配時
                sOrder++;
            if (str1.length() == sOrder) { // 完全匹配時
                System.out.println("succeed to find at " + (i - sOrder + 1)); // 輸出模式字串的第一個字元在主字串的位置
                return ;
            }
        }
        System.out.println("no matching, fail to find"); // 輸出沒有匹配到
    }
 
    public static void main(String[] args) {
        String str = "abcdababaabababcacbaccfabfcdabcdf";
        String str1 = "abababca";
        getKMP(str, str1);
        int[] array = getNextArray(str1);
        for (int i = 0; i < array.length; i++) {
        	System.out.print(array[i] + " ");
        }
    }

	
	
}