05.KMP算法之深度解析(二)

0 1 2 3 4 5 6 7 8 9 10
S: a b c a b a b c a b x
P: a b c a b x
多餘 a b c a b x
多餘 a b c a b x
a b c a b x
a b c a b x
匹配 a b c a b x
KMP算法:
a b c a b x
匹配: a b c a b x
  • 因爲第一次匹配時,在S[5] != P[5](a != x)處失配,按照暴力匹配算法,此時應判斷S[1] 與P[0]是否相等,發現不相等,則繼續判斷S[2]與P[0],發現不相等,則繼續判斷S[3]與P[0],發現相等,判斷S[4]與P[1]是否相等。其實以上4步完全是多餘的
  • 多餘的原因:在第一次匹配時,我們已經知道S[0]-S[4]與模式串P的部分匹配關係(P[0]-P[4])即:S[5]之前的都已經知道和模式串P的匹配關係了,不需要重寫回溯S來判斷了,因爲abcab的最大前後綴匹配個數爲2,即:S的後綴:S[3]-S[4]與P的前綴P[0]-P[1]是匹配的,則只需要從P[2]與S[5]開始判斷即可(如果字符串不存在前後綴匹配,則從P[0]開始匹配,例如ab的最大前後綴匹配個數爲0,則判斷S[5]與P[0]是否相等,相等,則i++,j++繼續向後匹配
0 1 2 3 4 5 6 7 8 9 10
S: a a a a b c d e f
P: a a a a a x
多餘 a a a a a x
多餘 a a a a a x
多餘 a a a a a x
多餘 a a a a a x
a a a a a x
KMP改進:
a a a a a x
a a a a a x
  • 第一次匹配,S[4] !=P[4],此時應用KMP算法,應將S[4]與P[3]比較,但是因爲P[3]=P[4],所以S[4]與P[3]的比較是多餘的,我們已經知道他們的大小關係。同理,P[2]、P[1]、P[0]與S[4]的比較都是多餘的。
  • next值的含義:找到模式串中的一個位置k,使得P[k]的值與剛纔失配的S值比對,以此省略大多數沒有用的步驟。但是我們不希望找到的這個P[k]的值和P[j]的值相等,因爲我們知道P[j]與失配處的S的關係。
  • 所以,當P[j] == P[next[j]]時,我們應該找P[next[j]]的下一個next值對應的P值來與剛纔失配的S進行匹配。

KMP算法的核心:通過利用已經匹配了的P的信息,來儘可能的減少沒有必要的步驟,通過P的信息可以知道下面有多少步驟是可以直接省略的,也就是知道,下面有多少步驟的匹配關係是已知的。

一個字符串,前綴、後綴相等的個數的意義是什麼?

abcabx

  • 最大前綴、後綴匹配個數:2(與字符串的最後兩位纔有可能匹配
  • 存在的前綴、後綴匹配個數:2
a b c a b x失配的地方
一定不匹配 a b c a b y
一定不匹配 a b c a b y
可能匹配(y!=c,所以c匹不匹配不知道) a b c a b y

aaaaax

  • 最大前綴、後綴匹配個數:4(與字符串的最後4位纔有可能匹配)
  • 存在的前綴、後綴匹配個數:1、2、3、4
  • 從匹配個數最多的開始找,順序爲:4、3、2、1
a a a a a x
可能匹配(a!=y,所以匹不匹配不知道) a a a a a y
一定不匹配(已知a不匹配了,而下一個next值對應的又是a,顯然不匹配) a a a a a y
一定不匹配 a a a a a y
一定不匹配 a a a a a y
一定不匹配 a a a a a y
改進的KMP:直接跳到next爲-1 a a a a a y
  • 因爲P[j]的next對應的值等於P[j],而我們的目的是匹配我們不知道的P。所以我們要繼續尋找下一個next值,直到找到不等於P[j]爲止,或者找到的P爲P[0]爲止。(此處找next的過程爲一個遞歸的過程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章