1. KMP算法用途算法
KMP算法用於解決主字符串和模式字符串匹配的問題。若是完成匹配,返回模式字符串在主字符串匹配的初始索引。若是不匹配,返回-1。數組
2. PMT(Partial Match Table):部分匹配表(模式字符串)spa
部分匹配表是KMP算法的核心,定義:前綴集合和後綴集合交集中最長元素的長度。3d
前綴集合:若是字符串M = A + S,A和S非空,則A是M的一個前綴,全部的前綴組成前綴集合。code
後綴集合:若是字符串M = A + S,A和S非空,則S是M的一個後綴,全部的後綴組成後綴集合。blog
圖中表示了Index = 10時,PMT = 4的計算過程,前綴字符串abab與後綴字符串abab匹配。索引
3. KMP算法實現字符串
若是主字符串是T,匹配字符串是P,T[ i ] != P[ j ]時,此時能夠經過右移匹配字符串PMT[ j - 1 ]個單位來解決,即令 j = PMT[ j - 1]get
若是T[ i ] = P[ j ],則i++, j++,表示目前匹配class
若是T[ i ] != P[ j ]
若是 j == -1,則須要 i++, j++,j++ 表示P 從0開始匹配,i++表示當前不匹配,從下一個位置開始匹配。
若是 j != -1,則從後綴字符串與前綴字符串已經匹配,令 j = next[j]便可。
循環結束,當 j == strlen(p)時,表示徹底匹配,此時返回 i - j 表示匹配的起始位置。
例:主字符串:"abababcab",子字符串:"ababc"
匹配過程:
爲了簡化計算,引入next數組記錄 j 索引處 PMT[ j - 1 ]的數值。
代碼實現
int KMP(char * t, char * p) { int i = 0; int j = 0; while (i < strlen(t) && j < strlen(p)) { if (j == -1 || t[i] == p[j]) { i++; j++; } else j = next[j]; } if (j == strlen(p)) return i - j; else return -1; }
4. PMT, next實現過程
經過移動與自身字符串匹配求next:
注意:若是不匹配,j 的值應該設爲:next[j],繼續向下匹配,直到爲 j = -1 爲止再從0開始匹配,下圖說明了緣由。
代碼實現:
void getNext(char * p, int * next) { next[0] = -1; int i = 0, j = -1; while (i < strlen(p)) { if (j == -1 || p[i] == p[j]) { ++i; ++j; next[i] = j; } else j = next[j]; } }