KMP模式匹配算法之 next[ ] 數組求值(天勤詳解)


算法執行過程可以參考視頻,看完了有個清晰的認知:

https://www.bilibili.com/video/BV1jb411V78H

代碼如下:

字符串結構體

// 變長分配存儲表示
typedef struct{
	char *ch;	 // 指向動態分配存儲區首地址的字符指針
	int length;  // 串長度
}Str;

獲取 next[ ] 數組值:

void getNext(Str subStr, int next[ ] ) {
    int i=1, j=0;  // 串從數組下標1位置開始存儲,因此i 初始值為1,
    next[1] = 0;
    while(i < subStr.length) {
        if (j==0 || subStr.ch[i] == subStr.ch[j]) {
            ++i;
            ++j;
            next[i] = j;
        }else{
            j = next[j];  // 回溯j值
        }

    }
}

配合下圖,對代碼的執行過程進行詳解。

案例

假設有模式串 = “A  B  A  B  A  B  B  C  D  A  B  ”

其next[ ] 數組快速的計算結果,可以根據視頻中的方法快速手算,如下:

分別用不同的顏色代表相應的字串與計算結果,此為快速計算next[ ] 的方法。

代碼過程

根據KMP算法 next[ ] 數組的值,案例對着上面的代碼運行過程如下:

注解:

代碼中 if 條件
if (j == 0 || subStr.ch[i] == subStr.ch[j])
簡記為  if 1  ||  2 : 
如果條件1成立記為 1√,條件2成立記為2√,不成立即為 x

1)根據不同的顏色可以看到next[ ] 賦值的來源 ;

2)回溯——根據程序,i 的值一直處於順增,菱形標注了i 的值的變化;但是 j 的值在 if 條件不滿足時,根據 j = next[j],進行回溯;如 Loop7的時候,j值為7,第一次回溯為3,第二次回溯為1,第三次回溯為0,然后if 條件滿足,此時j增為1,保證了 next[i] 除了在初始化的特殊狀態下為0,之后 next[ ] 的最小值也只能是1;

3)個人認為 next[ ] 的實際含義是當前字符位置在匹配串中有多少個字符已經匹配相同

搞清了next[ ] 的數值,下面來看如何在KMP主程序執行

KMP主程序

代碼:

int KMP(Str str, Str substr, int next[]) {
	int i=1, j=1; // 串從數組下標1位置開始存儲,因此初始值為1
	while(i <= sub.length && j <= subStr.length){
		if (j ==0 || str.ch[i] == subStr.ch[j]) {
			i++;
			j++;		
		}else {
			j = next[j]
		}
	}
	if (j > subStr.length) {
		return i - subStr.length;
	}else 
		return 0;
}

剖析:

1)仍然是通過 j = next[ j] 進行回溯的,僅僅是通過取出 next[ ] 里面的值;j 代表模式串和匹配串相同的字符集的個數;

2)i 確定位置,i - subStr.length 即可獲取模式串在匹配串中的初始位置。

那么如上圖求 next[ ],可以看到 j 在回溯的過程中,需要回溯多次計算跳躍值,存在重復計算已有值的情況,那么能不能讓 j 只需要回溯一次就可以確定前面有多少個字符串匹配呢?這就是改進的KMP算法要做的事了。

注:本代碼來源於天勤教材,具備科學性

喜歡就點左側支持下吧?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM