kmp:串的模式匹配算法
字符串匹配就是在一个主串中找到待匹配串的位置
主串: a b a b c a b c a c b a b
模式串: a b c a c
一
o(n*m)基本思想: 从主串 s 的第一个字符起和模式的第一个字符比较之,若相等,则继续逐个比较后序字符,否则从主串的第二个字符起再重新和模式的字符比较之。依次类推,直至模式 p 中的每个字符依次和主串s 中的一个连续字符序列相等,则称匹配成功,否则匹配不成功。
二 kmp算法
此算法可以在 O(n+m) 的时间上完成串的模式匹配操作。
基本思想是每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。
我们用两个指针i和j分别表示,S[i-j+1…i]与P[1…j]完全相等。也就是说,i是不断增加的,随着i的增加j相应地变化,且j满足以S[i]结尾的长度为j的字符串正好匹配P串的前 j个字符(j当然越大越好),现在需要检验S[i+1]和P[j+1]的关系。当S[i+1]=P[j+1]时,i和j各加一;什么时候j=m了,我们就 说P是S的子串,并且可以根据这时的i值算出匹配的位置。当S[i]!=P[j],KMP的策略是调整j的位置(减小j值到next[j])使得S[i-j+1…i]与P[1…j]保持匹配且新的P[j+1]恰好与S[i+1]匹配(从而使得i和j能继续增加)。
next数组的求法:
makeNext(string p, int *next)
/* 变量next是数组next的第一个元素next[0]的地址 */
{ int j, k;
k= -1; j=0; next[0]= -1; /* 初始化 */
while (j<p.length()-1) /* 计算next[j+1] */
{
if(k<0 || p[j]= =p[k])
next[++j]= ++k;
else
k=next[k];
}
}
得到next后的算法框架
int index(string p,string s, int *next)
{ int i,j;
int M=p.length(), N=p.length();
i=0; j=0; /*初始化*/
while (i<N && j<M) /*反复比较*/
if (j<0 || s[i]= =p[j])
{ i++; j++; }
else j=next[j] ;
if (j>=M)
return( i - M + 1); /*匹配成功*/
else
return( -1 ); /*匹配失败*/
}
例题:COGS [POJ 3461] 乌力波