演算法 - KMP演算法
阿新 • • 發佈:2018-11-28
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] + " "); } } }