算法整理——KMP算法

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 variable
		bool 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 ;
		}
	}
}

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值