字串之KMP演算法

2021-07-22 14:59:30 字數 1929 閱讀 7657

kmp演算法全稱knuth-morris-pratt演算法,是一種字串匹配演算法,常規字元匹配是每次移動一位,複雜度o(mn);而kmp演算法複雜度o(m+n)。

kmp演算法利用的是目標字串(要匹配的字串,如下圖第二行)前字尾有相同的子字串和在匹配過程中前i-1個字元已經匹配過的規律。

匹配過程:

部分匹配表:

從第一張圖中我們看到當我們目標字串第一位與被匹配字串字元相等時,我們向後移動指標,逐個匹配後面字元是否相等。當匹配字元d時,被匹配字串為空字元,顯然不等。這時與常規方法將目標字串整體向後移動一位不同。kmp演算法根據部分匹配表,d前面字元為b,對於值為2,將字串移動4位(移動位數=已經匹配字元abdcab長度6-字元b在部分匹配表中對應值2=4),這是目標字串前面的ab就移動到後面ab所在位置了。

從上圖變化中,我們看到了我們利用abdcab有相同前字尾ab,在我們比較到字元d位置後,字串abdcabd前面的字串abdcab已經比較過了,利用這個資訊,我們直接把字首移動到字尾位置,完成移動k位。

關於此處為什麼可以直接移動4位,我們已經匹配到第一張圖所在位置,此時d匹配不符合。常規情況下我們後移一位,但是我們要明白往下移動一位我們仍要匹配到ab,也就是說如果後移一位後我們目標字串從0位開始重新匹配,至少在相應位置上仍然需要ab。而kmp演算法利用我們已經知道子字串abdcab字尾有ab,而且我們已經匹配過了,知道接下來的ab在被匹配字串上的位置。也就是說在ab前面的b,d,c位已經顯然不可能匹配成功了。

字首:除最後乙個字元,前面字元的組合

字尾:除第乙個字元,後面字元的組合  

如上圖:目標字串abdcabd

字首有:[a] [ab] [abd] [abdc] [abdca] [abdcab]

字尾有:[d] [bd] [abd] [cabd] [dcabd] [bdcabd]

由前字尾的關係,我們可以算出一張表:

對於字串a:前字尾為空集,公共元素為0;

對於字串ab:字首[a],字尾[b],公共元素為0;

對於字串abd:字首[a] [ab],字尾[bd] [d],公共元素為0;

對於字串abdc:字首[a] [ab] [abd],字尾[bdc] [dc] [c],公共元素為0;

對於字串abdca:字首[a] [ab] [abd] [abdc],字尾[bdca] [dca] [ca] [a],公共元素為1。長度為1;

對於字串abdcab:字首[a] [ab] [abd] [abdc] [abdca],字尾[bdcab] [dcab] [cab] [ab] [b],公共元素為1。長度為2;

對於字串abdca:字首[a] [ab] [abd] [abdc] [abdca] [abdcab],字尾[d] [bd] [abd] [cabd] [dcabd] [bdcabd],公共元素為1;長度為3;

如下表:

這裡必須是字首和字尾相同。如果不是字首而是中間綴的話我們就不能判斷中間綴前面的字元能否跟被匹配字串匹配上。所以需要從頭開始,也就是從字首開始匹配。

leetcode之two su

字串 之 KMP演算法

kmp演算法是一種改進的字串匹配演算法,由d.e.knuth與v.r.pratt和j.h.morris同時發現,因此人們稱它為克努特 莫里斯 普拉特操作 簡稱kmp演算法 在介紹kmp演算法之前,先介紹一下bf演算法。一.bf演算法 bf演算法是普通的模式匹配演算法,bf演算法的思想就是將目標串s的...

字串之KMP演算法

kmp演算法用於字串匹配 比如 如何在 abdasjfasdfnadj 中判斷是否存在sjf,以及匹配的位置 容易想到的是將sjf挨個與母串進行匹配,當不匹配時,子串右移一位,繼續挨個匹配,這樣的話,複雜度為o mn 可以發現,這個暴力的方法中存在一些重複,子串右移一位,相當於忽略了上次匹配時的資訊...

字串匹配之KMP演算法

以前零零散散做了些kmp的題目,一直也沒找出時間整理,這一段又開始研究字串了,就順便把kmp整理了一下。廢話不說了,我們直接入題。說到kmp,首先應該知道,它是一種字串查詢演算法,因為是由乙個姓k,乙個姓m和乙個姓p的人聯合發表的,所以就叫kmp演算法了。kmp演算法是一種線性時間的的字串匹配演算法...