KMP字串匹配(C )

2021-09-28 07:37:04 字數 2215 閱讀 2372

字串匹配:求乙個字串是不是另乙個字串的子串(下文稱為主串和模式串)

kmp能夠達到o(n+m)的時間複雜度,而暴力匹配(樸素匹配)則需要花費o(nm)的時間。

例題:判斷aaab是不是aabaaaab的子串

暴力匹配:

按順序乙個乙個匹配,失敗了重新開始(主串向前移動一位,模式串回到第一位)

重複這個動作,直到最後

匹配成功

****************************************=

kmp匹配

上述有冗餘的部分,即模式串每次匹配失敗都要回到第一位,主串也要回到和模式串第一位對應的位置,這就是複雜度o(nm)的原因。在匹配失敗時,能否利用已知的資訊,使得主串不用回滾,這樣就只遍歷主串一遍就能得出結果。方法是有的,這就是next陣列,next陣列說明了模式串每乙個位置的字元在匹配失敗時,當前匹配位置要回到之前的哪個地方。kmp的主要目的就是求出這個next陣列。

具體表現形式,上述匹配會出現這種情況

樸素匹配發生匹配錯誤,將主串和模式串的匹配位置回滾,下一步是這樣做

kmp發生匹配錯誤,通過next陣列知道要回到下標2的位置,主串不用回滾,所以下一步是這樣

也就是說它直接跳過前兩位的匹配,因為這兩位本來就是一樣的,為什麼還要再匹配一遍?

所以問題就轉到next陣列上,它為什麼知道要回到下標2的位置進行匹配,那我們就要知道這個next陣列是怎麼生成的。這有點像是乙個預處理的過程。

先說明兩個名詞,字串的字首和字尾,例如:

aaab的字首有:a,aa,aaa

aaab的字尾有:b,ab,aab

在最後乙個匹配失敗時,我們知道前面那些都是匹配上的,即相同的。

前面匹配上的那些又是模式串的內容,所以在前面找到最長的字首和字尾匹配,我們就可以把整塊挪過去,就不會是樸素匹配那樣乙個位置乙個位置挪。換句話說,next陣列的值就是(字首和字尾相同的最長長度)

紅色框就是完全匹配上的,綠色框也是完全相同的,所以下次匹配就是這樣子

這就是next陣列的原理,只要知道怎麼求字首字尾的相同的最大值,就能解決。

******************************====

雖然是說ac自動機=kmp+字典樹,但我看了ac自動機再回來看kmp挺清晰的。kmp就是乙個單節點的樹。

#include#include#includeusing namespace std;

const int n = 1000100;

int n, m;

// n 主串長度, m模式串長度

char a[n], b[n];

// a 主串, b 模式串, 下標從零開始

int nextt[n];

vectorans;

void get_nextt()

}void get_nextval()

else

}}int kmp_index(int pos)

else

}if(j >= m) return i-m;

else return -1;

}int kmp_count(int pos)

}else

j = nextt[j];

}return ans;

}int main()

for(int i=1;i<=m;i++)

return 0;

}

kmp字串匹配

首先要對模式串進行預處理。預處理過程就是計算出指定位置的字首和字尾的最大相同的長度 啊啊啊啊。估計只有我乙個人能看懂 這個文章說得很清楚 比如說 a a a c b c a a a 0 1 2 0 0 0 1 2 3 void getnext int next,char par 20 int n 翻...

字串匹配 KMP

參考 從頭到尾徹底理解kmp 在字串 str 中 匹配模式串 pattern 1.計算模式串的 next 陣列 2.在字串中匹配模式串 當乙個字元匹配時,str i pattern k 繼續匹配下乙個字元 當當前字元不匹配時,根據 next 陣列移動模式字串,k next k next 陣列 描述模...

KMP字串匹配

判斷s中是否含有字串t。一般思路為 從s中首字元開始,依次與t中進行比對,直到t結尾或者某乙個位置兩者不同 如果到t的結尾,則表示s中含有t。如果有乙個位置不相同,那麼從s中下乙個字元開始,再次與t中字元比對。如下 i 0,j 0 for i len 這樣的比較,每一次遇到不同的時候都需要從t串的第...