對於KMP演算法的理解
阿新 • • 發佈:2021-02-09
技術標籤:資料結構的學習(C++)
KMP演算法是三位偉大的計算機先驅:D.E.Knuth、J,H,Morris 和 V.R.Pratt提出的,取其姓名首字母得名KMP,KMP演算法是為了優化暴力匹配而誕生的。暴力匹配時,較長的文字串指標會多次回溯使得程式效能下降,而KMP的核心思想就是減少匹配時主串(較長的文字串)指標的回溯次數以提升程式效能。
KMP的具體概念就不寫了,直接看這位博主的吧:
KMP演算法—終於全部弄懂了
如果實在不懂KMP的話建議看下某一年《王道考研·資料結構》鹹魚學長的講課視訊,十分易懂,比強行啃書本效率高得多。我按照《王道考研·機試指南》和《王道考研·資料結構》的視訊綜合寫出瞭如下的程式碼,以供自己以後翻閱和備考複試。註釋十分詳盡,如下所示:
#include<iostream> #include<string> using namespace std; //定義next陣列相關 const int MAXN = 10000; int nextTable[MAXN]; void generateNextTable(string pattern) { int m = pattern.size();//取得模式串長度 int j = 0;//用於遍歷模式串 nextTable[j] = -1;//設定萬用字元 //next[j]陣列的含義是: //當前模式串的下標遍歷到j //此時匹配失敗時,需要回溯到的下標位置 //該下標位置存放在陣列next[j]裡 //i用於計算nextTable的具體內容 int i = nextTable[j]; while (j < m) { if (i == -1 || pattern[j] == pattern[i])//成功匹配 { i++; j++; nextTable[j] = i; /* //按照虛擬碼next[j+1]=next[j]+1來寫的話,因該是: nextTable[j+1]=nextTable[j]+1; i++;j++; //上文nextTab[j]=i,只是因為先進行了i和j的自增 //本質時一樣的 */ } else//匹配失敗 { i = nextTable[i]; } } return; } int KMP(string text, string pattern) { //先生成輔助陣列next,才可以進行KMP演算法 generateNextTable(pattern); //取得文字串長度 int n = text.size(); //取得模式串長度 int m = pattern.size(); //i用於遍歷文字串text,j用於遍歷模式串pattern int i = 0; int j = 0; while (i < n&&j < m) { if (j == -1 || text[i] == pattern[j])//匹配成功 { i++; j++; } else//匹配失敗 { j = nextTable[j];//根據已有的next陣列回溯 } } if (m == j)return i - j;//成功匹配完成全部的模式串,返回首次出現位置 else return -1;//沒能匹配完成全部的模式串 } int main(void) { string pattern, text; getline(cin, text); getline(cin, pattern); cout << KMP(text, pattern) << endl; system("pause"); return 0;
這是輸出示例: