MP算法详细过程解析

目的:判断目标串(T串)中是否含有模式串(P串),在下文中为了方便,命名目标串为“长串”,模式串为“短串”。

显而易见的是,不断判断字符是否相同的过程就是两个指针移动的过程。MP算法就是要相比于暴力搜索BF,简化指针移动的过程。

首先对图中的标识做解释,黄色填充代表长串指针的移动,红色字符代表匹配失效的时刻,绿色填充的数字代表列,也是长串每一个字符的索引值,蓝色填充数字代表短串的索引。   

MP算法过程:长串的指针从来没有回溯。长串指针移动规则:长串在与短串的第一个字符匹配失败时指针向前移动一个位置,长串在短串某个字符匹配成功时向前移动一个位置,长串在与短串(除第一个字符)的某字符匹配失败时不移动指针。短串指针移动规则:若在短串的j位置匹配失败,下一次的匹配位置移动到f(j-1)+1 的位置。   

好了,按照这个规则我们用按图索骥走一遍吧。第一次匹配失败发生在第1列(绿色列),并不是短串的第一个字符失匹,长串指针不动,短串指针j=1(蓝色索引),下一次(f(1-1)+1)=0,指针到0索引,也就是第一个字符。第二次不匹配发生在短串的第一个字符,长串指针移动一个,短串指针仍在第一个字符。第三次不匹配发生在第八列,因为不是短串的首字符,长串指针不动,短串指针j=6,f(6-1)+1=2,指针移动到索引为2的字符。第四次不匹配,失匹字符不是短串第一个,所以长串指针不动,短串指针j=2,f(2-1)+1=0,指针移动到索引0字符。最后一直在匹配,长串指针向前走。     MP好处:长串没有回溯。从第三次不匹配到图中第四次,短串走了很远。肯定要比暴力一次走一步搜索速度快。至于为什么,就是因为短串中前部分子串和后部分子串有可能相同,这就导致移动的时候可以多移动点,用文字我解释不清楚,大家再想想吧。



void MP(string T, string P){
		int lenT = T.length();//长
		int lenP = P.length();//短
		vector<int> v(lenP + 1, 0);
		MP_bulid_v(v, P);
		int i = 0, j = 0;//i是短串的指针 j是长串的指针
		//整个过程就是两个指针的移动
		while (j < lenT){
			while (i>-1 && P[i] != T[j])
				i = v[i];
			i++;
			j++;
			if (i >= lenP){
				//成功找到一组
				cout << j - i;
				i = v[i];//接下来找下一组
			}
		}


	}
	void MP_bulid_v(vector<int> &v, string &P){
		int m = P.length();
		int i = 0;
		int j = v[0] = -1;
		while (i < m){
			while (j>-1 && P[i] != P[j])
				j = v[j];//这里的实现非常巧妙 很难想到
			i++;
			j++;
			v[i] = j;
		}
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值