圖解KMP以及next數組的求法


在計算機科學中,Knuth-Morris-Pratt字符串查找算法(簡稱為KMP算法)可在一個主文本字符串S內查找一個模式串P的出現位置。此算法通過運用對這個模式串在不匹配時本身就包含足夠的信息來確定下一個匹配將在哪里開始的發現,從而避免重新檢查先前匹配的字符。

今天寫完kmp的題, 發現又想不通了, 這個next數組實在是太繞了, 去跑步的路上不禁一直在想, 終於恍然大悟了! 感覺十分有必要寫一篇解釋, 用自己的話說說kmp以及這個next. 一方面加深一下印象, 另一方面希望給偶然看到的人一點點啟發 (

簡介

1591891392894

首先, 如果我們用傳統的方式來匹配這個字符串, 會得到如下的過程:

1591891426332

如果用KMP算法, 將減少無用的挪動 :

1591891464981

這么看可能還看不出什么, 如果我們稍微變化一下就可以看到KMP算法的巨大優勢 :

1591891527801

對於上圖這種匹配, 普通的暴力算法將遠遠落后於kmp

kmp工作機制

1591891577613

如果你不知道"前后綴" 也許以下的圖能更好的幫助理解

1591891640088

上圖來源於這里

匹配過程

1591891731199

為什么是剛好跳轉到next[i]

1591891783229

比如上面這個圖中, 接下來我們會將失配位置移動到P[2]也就是A的地方(右移兩下), 如果我們少移, 是不可能匹配的, 不然的話公共前后綴長度會比當前的值大

next數組的編程求法

重點 : 弄明白j回溯的原理

建議對照代碼觀看 :

int i = 0, j = -1;
	while(i < s.size()) {
		if(s[i] == s[j] || j==-1) {
			i++;
			j++;
			next.push_back(j);
		}
		else {
			j = next[j]; // 如果s[i]!=s[j]說明匹配失敗, 回到上一級公共前后綴處
		}
	}

我們列出兩個相鄰的指針i和j, 初始指在數組前和0號元素的位置

接下來我列出從0開始求出next數組的圖示

1591892292407

1591892301117

1591892307413

1591892314241

1591892322770

這里再附上兩個寫的不錯的鏈接

http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html

https://www.bilibili.com/video/BV1Px411z7Yo?t=1068



好累啊


免責聲明!

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



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