資料結構與演算法c 實現(5)之KMP匹配演算法

2021-09-25 22:17:25 字數 3039 閱讀 1440

我們都用過word中的查詢功能,這個查詢功能就是匹配演算法的應用背景。在主串中找到子串,並返回子串在主串中的位置。

假設我們的主串是s= 「goodgoogle」,子串t=「google」。要想在主串中找到子串最簡單的做法如下:

這是另外的一種**實現:

#includeusing namespace std;

//int bfmatching(string s,string t)

// }

// else

// }

// }

// return -1;

//}int bfmatching(string s,string t)

else

} if(j == len_t)

else

}int main()

我發現同樣的思想但是寫出來的**,卻可以相差很多。

kmp演算法是從上面的暴力演算法改進來的。

上面的這張還是暴力演算法的過程,當我們仔細觀察這個過程,就會發現其中的第2、3、4、5步都是多餘的。

如上圖,我們已知子串中t[0] != t[1],如果s[1] == t[1],那麼t[0] != s[1]是一定的,我們就不用去驗證這已經確定的事實,如果我們能夠通過某種方式跳過了這種多餘的操作,這就是我們的kmp匹配演算法。上面的匹配過程就會簡化為:

有人會問上面舉的例子是子串中沒有重複的字元,那麼如果出現了重複的字元,我們該怎麼做呢?

可見在上面的這個例子中,我們的子串裡ab兩個字元重複出現啦,這個過程中的第2、3、4、5是多餘的。我們應該直接觀察第6步。

如果當前字元匹配失敗,我們就去找這個字元之前有沒有重複的字元小串。比如上面的例子,在「x」之前的字串是「abcab」,這時候我們找重複的字串就從「abcab」的開頭和結尾找,結果就是得到「ab」。這裡面蘊含的道理也很簡單,就是,我要在回溯j的時候,不同的字元我們沒有必要驗證肯定不同,重複的字元也沒有必要驗證,肯定一樣。

或者這樣想,next[j]就等於當前字元前面的字串中相同前字尾的個數。

#includeusing namespace std;

void calculate_next(int next,string& t)

else }}

int main();

calculate_next(next,t);

for(int i : next)

return 0;

}

結果:

-100012

對上述**的解釋:

我查詢了很多**,我真心看不懂,然後就自己動手寫了乙個。

字元是相等的,這時就不能比較t[j-1] == t[0],而應該比較t[j-1] == t[0+k]了。

#includeusing namespace std;

void calculate_next(int next,const string& t)

else }}

int kmpmatching(const string& s,const string& t,const int next)

else

else

} }if(j == len_t)

else

}int main()

如果上面的**都看懂了這裡就比較容易看懂啦

如上圖,當我們j = 5匹配失敗時,會根據next[5] = 3跳到j = 3,然後又不正確根據next[3] = 1跳到j = 1,然後又不正確但,我們根據next[1] = 0,跳到j = 0。其實這幾步都是多餘的,因為這幾個對應的字元相等,都是b,既然第乙個匹配不正確那麼所有的都會不正確,所以應該選擇最小的那個,即next[5] = next[3] = next[1] = 0

void calculate_next(int next,const string& t)

else

} //對next進行優化

for(int j = 0; j < t_size -1; j++)

} }

}

資料結構之KMP演算法

當j 1時,next j 0 其他情況,next j 1 next j max t的長度時m,時間複雜度為o m while迴圈的時間複雜度為o n 整個演算法的時間複雜度為o n m 樸素模式時間複雜度為o n m 1 m kmp演算法僅當模式與主串部分匹配時,才能展現其優勢。求模式串t的next...

C 資料結構之KMP演算法 詳解

kmp演算法是一種匹配演算法,用來進行匹配查詢。通過在子串的每一位都設定乙個與之對應的回溯陣列下標,降低演算法的時間複雜度。每乙個需要查詢的子串,該演算法都會給它生成乙個與之相對於的next陣列,用來進行回溯。假設需要查詢的子串為 string s aaababa 該串首位也用來存放資料 生成的ne...

資料結構與演算法 KMP演算法

給兩個字串 s1 s2 求s2在s1中是否出現過,出現過的話,給出在s1中的第乙個索引。首先根據s2維護乙個字首字尾表,比如 abbac 1,0,0,0,1 然後在與s1進行比較,比如 miabbabbac 與 abbac 首先有兩個下標指標分別分i,j s1 i 與s2 j 進行比較,不一樣。判斷...