KMP算法学习
(1) 參考網(wǎng)址:
KMP算法:?? http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html??
??????? --- 用遞推思想和直接法兩種方式求解next數(shù)組
KMP學(xué)習(xí)心得:?? http://www.java3z.com/cwbwebhome/article/article19/res023.html?id=3737
?????? --- 當(dāng)一個字符串以0為起始下標(biāo)時,next[i]可以描述為"不為自身的最大首尾重復(fù)子串長度"。
KMP字符串模式匹配中模式函數(shù):? http://www.java3z.com/cwbwebhome/article/article19/re022.html?id=3731
?????? --- 詳細(xì)講解了next數(shù)組的求解方法【next數(shù)組求解的改進(jìn)版本】
?
(2) 經(jīng)典總結(jié):
一、怎么求串的模式值next[n]
定義:
(1)next[0]= –1? 意義:任何串的第一個字符的模式值規(guī)定為-1。
(2)next[j]= –1?? 意義:模式串T中下標(biāo)為j的字符,如果與首字符相同,且j的前面的1~k個字符與開頭的1~k個字符不等或者相等但
????????????? T[k]==T[j](1≤k<j)。 如:T=”abCabCad” 則 next[6]=-1,因T[3]=T[6]? bCa
(3)next[j]=k????? 意義:模式串T中下標(biāo)為j的字符,如果j的前面k個字符與開頭的k個字符相等,且T[j] != T[k] (1≤k<j)。
?????????????? 即T[0]T[1]T[2]...T[k-1]== T[j-k]T[j-k+1]T[j-k+2]…T[j-1] 且T[j] != T[k].(1≤k<j);
(4)next[j]=0??????? 意義:除(1)(2)(3)的其他情況。
?
二、next 函數(shù)值究竟是什么含義
設(shè)在字符串S中查找模式串T,若S[m]!=T[n],那么,取T[n]的模式函數(shù)值next[n],
1. next[n]= -1 表示S[m]和T[0]間接比較過了,不相等,下一次比較 S[m+1] 和T[0]
2. next[n]=0 表示比較過程中產(chǎn)生了不相等,下一次比較 S[m] 和T[0]。
3. next[n]= k >0 但k<n, 表示,S[m]的前k個字符與T中的開始k個字符已經(jīng)間接比較相等了,下一次比較S[m]和T[k]相等嗎?
4. 其他值,不可能。
(3) 代碼實(shí)現(xiàn) 【參考書籍:《數(shù)據(jù)結(jié)構(gòu)與算法 Java語言描述》 鄧俊輝 著】
?
原書代碼:【略有改動】
package dsa; /** 串模式匹配:KMP算法*/ public class PM_KMP {public static void main(String[] args) {System.out.println(PM("ababacab", "aca"));}public static int PM(String T, String P) {// KMP算法int[] next = BuildNextImproved(P);// 構(gòu)造next[]表int i = 0;// 主串指針int j = 0;// 模式串指針while (j < P.length() && i < T.length()) {// 自左向右逐個比較字符ShowProgress(T, P, i - j, j);ShowNextTable(next, i - j, P.length());System.out.println();if (0 > j || T.charAt(i) == P.charAt(j)) {// 若匹配,或P已移出最左側(cè)(提問:這兩個條件能否交換次序?)i++;j++;// 則轉(zhuǎn)到下一對字符} else// 否則j = next[j];// 模式串右移(注意:主串不用回退)}// whilereturn (i - j);}protected static int[] BuildNext(String P) {// 建立模式串P的next[]表int[] next = new int[P.length()];// next[]表int j = 0;// “主”串指針int t = next[0] = -1;// “模式”串指針while (j < P.length() - 1)if (0 > t || P.charAt(j) == P.charAt(t)) {// 匹配j++;t++;next[j] = t;// 此句可以改進(jìn)...} else// 失配t = next[t];for (j = 0; j < P.length(); j++)System.out.print("\t" + P.charAt(j));System.out.print("\n");ShowNextTable(next, 0, P.length());return (next);}protected static int[] BuildNextImproved(String P) {// 建立模式串P的next[]表(改進(jìn)版本)int[] next = new int[P.length()];;// next[]表int j = 0;// “主”串指針int t = next[0] = -1;// “模式”串指針while (j < P.length() - 1)if (0 > t || P.charAt(j) == P.charAt(t)) {// 匹配j++;t++;next[j] = (P.charAt(j) != P.charAt(t)) ? t : next[t];// 注意此句與未改進(jìn)之前的區(qū)別} else// 失配t = next[t];for (j = 0; j < P.length(); j++)System.out.print("\t" + P.charAt(j));System.out.print("\n");ShowNextTable(next, 0, P.length());return (next);}protected static void ShowNextTable(int[] N, int offset, int length) {// 顯示next[]表,供演示分析int i;for (i = 0; i < offset; i++)System.out.print("\t");for (i = 0; i < length; i++)System.out.print("\t" + N[i]);System.out.print("\n\n");}protected static void ShowProgress(// 動態(tài)顯示匹配進(jìn)展String T,// 主串String P,// 模式串int i,// 模式串相對于主串的起始位置int j)// 模式串的當(dāng)前字符{int t;System.out.println("-------------------------------------------");for (t = 0; t < T.length(); t++)System.out.print("\t" + T.charAt(t));System.out.print("\n");if (0 <= i + j) {for (t = 0; t < i + j; t++)System.out.print("\t");System.out.print("\t|");}System.out.println();for (t = 0; t < i; t++)System.out.print("\t");for (t = 0; t < P.length(); t++)System.out.print("\t" + P.charAt(t));System.out.print("\n");System.out.println();} }?
精簡代碼:
?
package dsa.me;public class Kmp {public static void main(String[] args) {System.out.println(kmp("ababa", "bab"));System.out.println(kmp("ababa", "bba"));}// KMP算法public static int kmp(String T, String P) {int next[] = buildeNextImproved(P);int i = 0;int j = 0;while (i < T.length() && j < P.length()) {// 一定要限制它們在范圍內(nèi),不然會報錯if (j < 0 || T.charAt(i) == P.charAt(j)) {// 匹配,i和j都向右移動,j<0(j=-1)i++;j++;} else {// 不匹配,只要移動j,i不要回溯j = next[j];}}if (j >= P.length())return (i - j);elsereturn -1;}// 求next數(shù)組public static int[] buildeNext(String P) {int[] next = new int[P.length()];int j = 0;int t = -1;// 初始值是-1next[0] = -1;while (j < P.length() - 1) {if (t == -1 || P.charAt(t) == P.charAt(j)) {// 匹配---如果在j這里不存在首尾相同的字符串,那么next[j]就會等于0t++;j++;next[j] = t;// 由這里看出while條件中j不能等于P.length()-1} else {// 不匹配t = next[t];}}return next;}// 求next數(shù)組的改進(jìn)版本public static int[] buildeNextImproved(String P) {int[] next = new int[P.length()];int j = 0;int t = -1;// 初始值是-1next[0] = -1;while (j < P.length() - 1) {if (t == -1 || P.charAt(t) == P.charAt(j)) {// 匹配---如果在j這里不存在首尾相同的字符串,那么next[j]就會等于0t++;j++;next[j] = (P.charAt(j) != P.charAt(t)) ? t : next[t];// 改進(jìn)的地方} else {// 不匹配t = next[t];}}return next;}}?
附上參考書籍的對應(yīng)章節(jié)pdf下載地址:http://115.com/file/dpkg6art#數(shù)據(jù)結(jié)構(gòu)與算法(Java_描述).pdf
轉(zhuǎn)載于:https://www.cnblogs.com/yinger/archive/2012/07/15/2592072.html
總結(jié)
- 上一篇: 霍夫变换——HoughLines、Hou
- 下一篇: xpath爬虫-抓取全国行政区划和城乡区