码迷,mamicode.com
首页 > 编程语言 > 详细

[填坑][主线任务]MP&KMP算法

时间:2017-11-04 19:38:32      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:highlight   成功   内容   ges   技术分享   jpg   src   pre   自己   

当时一直就没有理解QAQ,觉得会hash就够了,但是想到fail数组有很多神奇的妙用,于是来填这个坑

技术分享


先讲MP算法:

我就直接说fail数组的含义吧(从0开始字符串下标):

fail[i]表示0~i-1这个串的最长border的长度,同时也是重新开始匹配的将要匹配的那个位置下标。

举个小栗子:对于字符串 abcdabd 

fail[6]=2,即abcdab的最长border的长度为2(ab),匹配失败的时候,下标跳到fail[6](为2)再来匹配,即从‘c’字母开始匹配(因为前边的‘ab’已经匹配成功了)

比如这个匹配:

技术分享

当匹配‘d’与空格失败后,fail[6]=2,跳到2再来拿‘c’去和空格匹配,而‘c’前边的‘ab’已经匹配成功了

所以我们的匹配代码是这样的:

void work() {
    int j=0;
    pos(i,0,len2-1) {
        while(j&&P[j]!=Q[i]) j=fail[j];
		//一直匹配不上一直往前跳,直到到了最开始或者匹配成功 
        if(P[j]==Q[i]) j++;//匹配成功继续向后匹配 
        if(j==len) {
            ans++;
            j=fail[j];
			//如果全串匹配成功了,直接跳到全串的fail,重新开始匹配 
        }
    }
}  

那么我们怎么求fail数组呢?其实就是自己和自己匹配

我们已经知道fail[i-1],即我们知道0~i-2的最长border,那我们求fail[i],就要拿p[i-1]和fail[i-1]去比较,如果相等就是fail[i]=fail[i-1]+1,如果不相等就相当于失配了,就再往前跳fail,直到跳到最开始或者找到可以匹配的位置

代码实现:

void getfail(){
	len=strlen(p);
	fail[0]=fail[1]=0;
	int k=0;
	pos(i,2,len){
		while(k&&p[k]!=p[i-1]) k=fail[k];
		if(p[k]==p[i-1]) k++;
		fail[i]=k;
	}
}

KMP算法:

MP算法中的fail是最长border,KMP算法有一丝丝的不同,就是fail数组存的是最优border  

代码实现就加了1行:

void getfail() {
    fail[0]=fail[1]=0;
    int k=0;
    pos(i,2,len) {
        while(k&&P[k]!=P[i-1]) k=fail[k];
        if(P[k]==P[i-1]) k++;
        if(P[k]!=P[i]) fail[i]=k;
        else fail[i]=fail[k];
    }
} 

就是说我们fail匹配到之后,我们需要再比较一下fail与当前位置,相当于借鉴一下前人的经验

意思就是说,如果我们接下来匹配的内容前边已经匹配过,显然注定会失败,所以我们的fail再向前跳一个,以达到最优的目的QvQ


接下来又是愉快的刷题:

 

[填坑][主线任务]MP&KMP算法

标签:highlight   成功   内容   ges   技术分享   jpg   src   pre   自己   

原文地址:http://www.cnblogs.com/Hallmeow/p/7783908.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!