#includeusing namespace std;
int next_[1005],len1,len2;
char str[1005],sub_str[1005];
void kmp(){
int k = -1,i = 0;
next_[0] = -1;
while(i>str>>sub_str){
len1 = strlen(str);
len2 = strlen(sub_str);
kmp();
for(int i = 0;i求出next陣列(先不解釋),然後子串從頭開始匹配,如果在子串的位置i處失匹了,那麼子串跳到next[i]的位置繼續和母串匹配,這樣,母串只需要遍歷一次,子串在不停的往回跳動。
那麼我們怎麼知道子串失匹時往回跳多少呢,這樣跳為什麼正確呢?
針對這倆個問題,給出如下證明:
對於子串 0 -- i-1 ,我們找到最長的字首串 0---k1 和 最長字尾串k2----i-1,使得這倆個串是相同的,這個是可以存在的對吧,例如
0 1 2 3 4 5 6 7 8 9
a b c a d e a a b c
那麼 i-1 = 9 ,此時k1 = 2 , k2 = 7 。找到了最長的字首字尾匹配串,先不管怎麼找到的。找到之後我們發現乙個最大的趣事:當位置i = 10(此處沒有給出i的字元是多少)和母串失匹時,我們是知道前0 - 9 和母串是匹配的,那麼優化條件就來了,我們的最大字首串等價於最大字尾串 已經和母串匹配過 ,所以我們從位置i跳到 3位置讓子串的3位置和母串繼續匹配,因為母串前面的三個字元和子串的字尾串是匹配的,而字尾串和字首串是相同的,所以字首串自然和母串的前面幾個字元匹配了。這個思路不僅僅只用在了這個演算法中,可以先了解下馬拉車演算法中對稱性完全匹配,再來證明這個問題就很簡單了。
假設存在乙個更加後面的位置x可以跳,即字首串和字尾串的匹配長度會大於之前我們通過kmp演算法預處理找到的next值要大,但是事實我們用kmp找到的字首字尾串相同的長度一定是最大的,這個證明留到後面解決。
先看看倆個標號為①的區間,這就是s[i]的字首和字尾相同的最長區間,那麼當i失去匹配的時候,我們跳到next[i]也就是k處,想想就知道,上面也證明了,右邊的 ①' 就是在匹配s[i]前剛和母串匹配完的部分,假如我們再重新將子串的左邊的 ① 區間和母串匹配是不是浪費了大量的不必要的時間,所以我們跳到k處繼續和母串匹配就行了。
這裡根據圖給個證明,就是next[i]已經求出來了,是k,但是現在要得到next[i+1]怎麼辦?,我們發現,在s[i]的字首和字尾(也就是倆個區間①)中,如果s[i] == s[k],那麼馬上就知道了next[i+1]==k+1的。
但是,最關鍵的問題,也是最難想通的來了,萬一在求next陣列時,我們的s[i]!=s[k]怎麼辦?一般人們會發現遞推的這個字首沒有用了,因為不連續了,的確!但是我們發現了個重要的線索!
假設next[k] == k' , 那麼區間②==區間②' ,因為這倆個分別是s[k]的最大匹配字首和字尾,但②'同時是①的字尾,所以②'也可以對應到①'的字尾,我們標記為②''。此時有② == ②' == ②'' 。
又因為② == ②'' ,所以我們只需要接著判斷s[k'] == s[i]?,
假如s[k'] == s[i]: 則表示假如子串在i+1處失匹,那麼可以跳躍到k' +1 處,繼續比較,因為 字串 ② + s[k'] == ②''+s[i] 。
假如s[k'] != s[i] ,我們發現這是個重複的問題,同理 接著找到k'' = next[k'] 繼續和s[i]比較,直到某個點滿足條件為止,當不存在匹配的點的時候,也表示我們此時必須將子串的第乙個s[0] 和母串重新匹配。
void new_kmp(){
int k = -1,i = 0;
next_[0] = -1;
while(i變化的部分只有:
為什麼kmp原型是在next[++i] != next[++k]的基礎上賦值的呢?
從上面的圖,我們又發現了問題:如果在s[i]處失匹,那麼我們當然希望跳躍到的新的位置s[k] != s[i]的,很顯然啊,因為你跳了之後字元還是一樣的,再拿去和母串匹配,不還是會失去匹配嗎,然後又得依照這個思路跳到新的next[k]處,那麼我們直接跳到next[k]處不就好了嗎?
當然,肯定有人問,為啥不拿while迴圈,直到不相等的條件下的next值再賦值,這個說的很好,我們發現在巢狀多個next值之後,這個跳躍也是很費時間的,所以沒有太多的必要去while迴圈找不相同的巢狀next的值。
字串匹配演算法 字串匹配演算法總覽
字串匹配在文字處理裡非常重要,我們採用簡潔的python 把以下演算法一一實現並講解。樸素演算法 algorithm rabin karp 演算法 有限自動機演算法 finite automation knuth morris pratt 演算法 kmp algorithm boyer moore ...
字串匹配演算法
首先引用一下另一篇文章中對字串匹配的介紹 字串匹配指的是從文字中找出給定字串 稱為模式 的乙個或所有出現的位置。本文的演算法一律輸出全部的匹配位 置。模式串在 中用x m 來表示,文字用y n 來,而所有字串都構造自乙個有限集的字母表 其大小為 根 據先給出模式還是先給出文字,字串匹配分為兩類方法 ...
字串匹配演算法
平常操作文字的時候,經常需要操作對字串進行操作。而字串中最重要的一種操作就叫匹配,字串的匹配演算法很多,人們最熟悉的莫過於kmp演算法了。今天就來談一談一些字串匹配演算法。先來說說大名鼎鼎的kmp演算法,這個演算法出現在無數的資料結構與演算法書上面。它的策略很簡單 當模式串第k個字元不匹配主串中第s...