KMP演算法介紹及時間複雜度分析
阿新 • • 發佈:2018-12-17
概念:字串中 一個字元前面的字串 的字首與字尾的最長匹配長度(短的那個字串)
注意:字首與字尾不可以是整個子字串
例如:a b c a b c d , d位置的最長匹配長度為3,abc 與 abc 匹配
Next陣列:長度與字串長度一致,每個位置儲存對應字元的最長匹配長度
Next陣列求解:
1.初始位置,由於第一個字元前面沒有字元規定, Next[0] = -1; 由於第二個字元前面只有一個字元,Next[1] = 0.
2.後續位置,使用數學歸納法,根據前面已經求過的陣列值來求取Next[i];
設字串為str:
如果str[i] == str[x1] , Next[i + 1] = Next[i] + 1;
否則把str[i]與str[x2]比較,如果相等,Next[i + 1] = Next[x1] + 1;
直到走到字串的第一個位置,求取Next陣列的程式碼如下:
vector<int> getNextArray(string str) { if (str.size() == 1) { vector<int> Next(1, -1); return Next; } vector<int> Next(5); Next[0] = -1; Next[1] = 0; int i = 2;//Next陣列中待求的位置 int cm = 0;//與str[i - 1]比較的位置 while (i < str.size()) { if (str[i - 1] == str[cm]) { Next[i++] = ++cm;//cm的值一直保持和Next[i - 1]一樣 } else if (cm > 0) { cm = Next[cm]; } else { Next[i++] = 0;//str[i - 1] != str[0] } } return Next; }
2.KMP演算法的比較過程
X與Y位置不匹配,根據X位置的匹配串長度,可以把圓圈位置的字元直接與Y比較,完成加速過程
int getIndexOf(string str1, string str2) { vector<int> Next = getNextArray(str2); int i1 = 0; int i2 = 0; while (i1 < str1.size() && i2 < str2.size()) { if (str1[i1] == str2[i2]) { i1++; i2++; } else if (i2 != 0) { i2 = Next[i2]; } else{ i1++;//一直後退到str2[0]都不相等,只有i1向前走一個 } } return i2 == str2.size() ? i1 - i2 : -1;//i2 == str2.size()代表str2走完了 }
主函式如下:
int main()
{
string match = "ababa";
string str = "abcabcababaccc";
cout << getIndexOf(str, match);
return 0;
}