理解KMP算法(引用)

理解KMP算法(引用)

通用性的 KMP算法
void getnext(st·t,int next[])/*由子串T求出next值*/
{int j,k;
j=O;k=一l;next[0]=一l;
while(j<t一>length—1)
{

if(k==一1 IIt一>ch[j]==t一>ch[k])/*检索存在最大的真子串,则用k对next函数赋值*/
{J++;k++;next[j]=k;}
else
k=next[k];/*滑动过程中如果出现不相等则认为以k个字符相等进行下一次滑动*/
}


kmpindex(St*s,st*t,int pos)/*MAXSTRLEN为一常量,用来定义数组*/
{
int next[MAXSTRLEN],i 2 pos—l,j=O;
gemextval(t,next);/*获取next函数*/
while(i<S一>len&&j<t一>len)
}if(j==一1 I I s一>data[i]==t一>data[j])
{i++;j++;}
else j=next[j];/*i不变,j通过next函数后退,与上一个算法的不同之处*/
}
if(j>=t一>length)
retum i—t一>length;/*返回的是目标串中匹配成功的第一字符下标*/
else
return一1;/*没有与子串匹配的字符串,则返回不匹配的标志*/
}

 

 


KMP算法的改进及其与子串滑动算法的整合
上述的KMP算法的next函数在某些情况下尚有缺陷.如果子串为“aaaab”在和目标串“aaabaaaab”
匹配时,当i=3√=3时,S一>data[i]≠t一>dataEj],由next[j]的指示还需要进行i=3,.『=2,i=3。J=
1,江3J=0等3次比较.实际上,因为子串中的第l、2、3个字符和第4个字符都相等,因此,不需要再
和目标串中的第4个字符比较,而可以将子串一次向右滑动4个字符的位置直接进行i=4,_『=O时的字
符比较.这就是说,若按上述定义得到next[j]=k,而子串中Tj=L,则当目标串中字符Si和T。比较不
等时,不需要再和L进行比较,而直接和Tnext[k]进行比较,换句话说,此时的next Ej]应和next[k]相
同.为此将求next函数的算法修正如下:
void getnextval(string奉t,int nextval[])
{int j,k;
j=0;k=一l;nextval[0]=一l;
while(j<t一>length)
{if(k==一l I lt一>chEj]==t一>eh[k])
{j++;k++;
if(t一>ch[j]!=t一>eh[k])
nextval[j]=k;
else
nextval[j]=nextval[k];/*出现Tj=Tk,实现改进*/
}
else

k=nextval[k];

}
}
改进后的KMP算法实际上就是对next函数的改进,在每次实现模式匹配时,都要求出nextval值之
后进行子串与主串的比较,也就是说在每次匹配都要求出子串的next值或nextval值.对于前面实现的
特殊问题用子串滑动算法来实现的匹配方法,也是一个比较好的简单匹配方法,由于简单、快捷,可以让
这个算法与KMP算法相结合,得到一个具体情况具体实现的模式匹配算法.这个算法的基本思想是:对
于一个子串,首先判断第一个字母是否重复出现,如果没有重复出现,则采用子串滑动算法,如果第一个
字母重复出现,则调用nextval函数,采用KMP算法.具体实现方法及其代码如下:
kmpsubindex(shing宰8 t string木t,int pos)
{
int next[MAXSTRLEN],i=pos—l,j=O,k;
for(k=l;k<t一>length;k++)/*判断是否符合直接滑动的标准*/
if(s一>ch[O]==s一>ch[k])break;
if(k>=t一>length)/*宰没有出现首字母重复*/
{while(i<s一>length&&j<t一>length)
{if(j==一lI I s一>ch[i]==t一>ch[j])/*j为一l时表示上一次是首字符不匹配*/
{i++;j++;}
else/*如果出现不匹配时,要为子串的整体移动作准备*/
{if(j==O)j=一l;/*整体移动有两种情况,即首字符不匹配和其它字符不匹配*/
else j=0;
}
}
}
else/*采用KMP算法*/
{getnextval(t,next);
while(i<s一>length&&j<t一>length)
{if(j==一1 I s一>ch[i]==t一>ch[j])
{i++;j++;}
else j=next[j];
}
}
if(j>=t一>lensth)/*两种比较情况可以归类*/
return i—t一>length;
else
return -1;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值