算法整理——KMP算法

来源:互联网 发布:量化交易的软件 编辑:程序博客网 时间:2024/04/29 08:59

KMP算法用于字符串匹配的问题,可以达到最好时间复杂度O(n+m)。其中n,m分别是文本串和模板串的长度。

传统的处理字符串匹配的方法是:遍历文本串的每一个字母,通过以这一个字母为开头的子字符串与模板串比较,当发现某一位不匹配时,跳出到执行下一个字母的检测。假设最坏情况,每一次都是模板的最后一个字母出错(比如文本串aaaaaaaaaaaab,模板串aaaab),需要的时间复杂度为O(n*m)。

KMP算法的精髓在于:对模板串进行预检测处理,当执行匹配时,发现了失配,那么可以充分利用预处理的结果跳过不必要的比较,直接在当前最为适配的位置进行比较。一个简单的例子,如果模板串是abcdef,当在‘e'位置比较时失配,我们可以知道此处文本串的前几个位置为”....abcd....“。从直觉上看,后面的几位都不应该再进行比较(不存在匹配)。所以模板串的预处理作用就是让程序拥有这种”直觉“。

预处理主要是对应模板串生成一个f[]数组,f取义为有限状态机(FSM)。

假如模板为temp[]

temp[]: a b c d a b g a b c f a

f[]:         0 0 0 0 1 2 0 1 2 3 0 1

f[]数组中非零项的数x表示当前位置的前x个字符与模板串的前x个字符相同。

有了f[]数组之后,就开始进行字符串的匹配。假如在模板串的(temp[7]=='g', f[7]=0)位置失配了,通过回看f[6]=='2',知道文本串此前两位为”ab“,与模板前两位一样,那么就可以将模板移到这里再重新开始比较,而之前前几位不可能存在匹配,就被跳过了。

前面提到的模板串

temp[]: a a a a b

f[]:         0 1 2 3 0

预处理函数

void handle_FSM(char* temp, int* tempFSM,int tempLen){tempFSM[0] = 0 ;for(int i = 1 ; i < tempLen ; i ++){if(temp[i] == temp[tempFSM[i-1]]){tempFSM[i] = tempFSM[i-1] + 1 ;}else{tempFSM[i] = 0;}}}

匹配函数

void KMP(char* str, int strLen, char* temp, int* tempFSM, int tempLen){int k = 0 ;for(int i = 0 ; i <= strLen - tempLen ;   ){//match variablebool match = true ;for(int j = k ; j < tempLen ; j++){if(temp[j] != str[i+j]){if(tempFSM[j]){i += j + 1;k = 0 ;}else if(j > 0 && tempFSM[j-1]){i += j - tempFSM[j-1];k = j ;}else{i += j + 1;k = 0 ;}match = false;break;}}if(match){cout << i << endl ;if(tempFSM[tempFSM[tempLen-1]]){i += tempLen - tempFSM[tempLen-1];}else{i += tempLen + 1 ;}k = 0 ;}}}

-------------------————如有问题,请积极联系本人,谢谢-------------------------------------------


0 0
原创粉丝点击