KMP算法

来源:互联网 发布:php数组键不为数字 编辑:程序博客网 时间:2024/06/06 05:28

KMP算法:

最经典的字符串匹配算法,即主串不回溯算法

eg:主串:abacabab  子串:abab

第一次匹配: 


第二次匹配:在第一次匹配中,主串与子串的第四个字符匹配失败,我们观察可知,子串中,第一个字符跟第二个字符不同,跟第三个字符相同,所以,直接将子串向右移动三个位置,子串的第二个字符跟主串的第四个字符开始匹配


第三次匹配:在第二次匹配中,子串第二个字符与主串的第四个字符匹配失败,所以从子串第一个字符开始跟主串第四个字符开始匹配


第四次匹配:在第三次匹配中主串的第四个字符与子串的第一个字符匹配失败,这是子串向右移一个位置,与主串的第五个字符相比较

 

通过四次匹配,最后主串和子串匹配成功。

通过上面的分析,我们可以看出,主串始终没有向前回溯。

我们假设,主串S中 i 位置的元素与子串T中 j 位置的元素匹配不成功,主串不回溯,子串回溯到k继续跟主串进行比较,那么存在以下结果:

T1...T(k-1)=s(i-k+1)...s(i-1); //k<=j-1

通过上面主串与子串的部分匹配可得:

T(j-k+1)..T(j-1)=s(i-k+1)...s(i-1);

那么这样就可以得到:

T1...T(k-1)=T(j-k+1)..T(j-1);

这个过程就表明,子串中可能存在想互重叠的子串。如果,将对于子串中j位置跟主串i位置不匹配时,那么就从子串的k位置开始跟主串的i位置进行比较的过程提取成一个式子:next[ j ]=k;

那么假设T(k)==T(j),那么根据上面的推导我们就可以知道next[ j+1 ]=k+1;如果T(k)≠T(j),next[ j ] = next[ k ],一次类推,最后得到next[ 1 ]=0

那么我们可以得到KMP的算法如下:

int kmp(String *mainStr,String *subStr) {

int i=0,j=0;

while(i<mainStr.length() && j<subStr.length()){

if(mainStr[ i ]== subStr[ j ]){

i++;

j++;

}else{

j=next[ j ];

}

}

if( j.>= subStr.length()){

return i-subStr.length();

}else{

return -1;

}

}

//求子串的next值,并将值保存到next数组中

void next(String *subStr , int next[ ]){

int i =1,j=0;

next [ 1 ] = 0;

while(i<subStr.length)

{

if((j==0) || (subStr[ i ] == subStr[ j ]) ){

i++ ; 

j++;

next[ i ]=j;

}else{

next[ i ]=next[ j ];

}

}

}



0 0
原创粉丝点击