kmp算法




kmp算法

       KMP,主要的思想是求next[]数组,next数组只与模式串有关,与主串无关,作为字符串匹配时出现不匹配的跳转之用,严 的书上next[1]=0,还是很不习惯这种表达方式,数组还是习惯从next[0]开始!

      严书上说,一串字符串p1.p2.p3...pn的next数组next[i]=j,表示p1..pj-1=p(i-j+1).....p(i-1),意思就是比如说字符串s1=acbcaac中(以1为下标开始)s[6]=a,s[7]=c,那么与s[6]对应的next[6]=2,表示的意思就是S[1]=S[5],假如

 s:abcdabcef,那么s[6]=b,next[7]=3(s[1].s[2]=s[5].s[6]),就从这种情况看吧,如果继续有s[3]==s[7],那么next[8]=4了吧!

还可以用写出前缀和后缀找出相等的串的方法求next数组,比如:s=abcdabc

a: :          next[1]=0

ab:    : 前缀:a   后缀:b  没有相等项next[2]=1

abc         {a ,ab}    {c,bc}    0      next[3]=1

abcd       {a,ab,abc}  {bcd,cd,d}  0   next[4]=1

abcda     {a,ab,abc,abcd}  {bcda,cda,da,a}  1  next[5]=2

abcdab  {a,ab,abc,abcd,abcda} {bcdab,cdab,dab,ab,a}  2  next[6]=2  s[1]=s[5]

abcdabc                                                                          3  next[7]=3    s[1].s[2]=s[5]s[6]

在主串T1与模式串T2的匹配过程中如果某时刻T1[i]!=T2[j],但是此时T2前面与T1肯定完全匹配,要不,不会匹配到这里来,然后再根据next[]数组找出与T2前面匹配的最大串长,即此时的next[j],与T2前面匹配了最大串长,那么毫无疑问与T1也匹配了吧,

举个例子:T1:acbcabacbcad T2:acbcaacd    next[]={0,1,1,1,1,2,2,3}

 (字符串的下标也从1开始吧)  在T1与T2匹配到T1[6]和T2[6]时不等了,那么T2要回溯,查next数组,next[6]=2,那么用T1[6]与T2[2]

继续比较,如果不等,继续以上面方式向前回溯,回溯到T2[1]时,继续向后比较,

如next数组和字符下标都是从0开始

void get_next(char *str,int next[])
{
     int i=0;
     int j=-1;
     next[0]=-1;//数组首元素置为-1,
     while(*(str+i)!='\0')//字符串遍历不为空时
     {
      if(j==-1||*(str+i)==*(str+j)){//回溯到next[0]或者相等时进入if
          i++;j++;  

      next[i]=j;//next数组就是一个模式串的自我前缀和后缀匹配,
                         }/
      
  j=next[j];//不等,继续回溯

 }

一种优化方法:

 

void get_next(char *str,int next[])
{
     int i=0;
     int j=-1;
     next[0]=-1;//数组首元素置为-1,
     while(*(str+i)!='\0')//字符串遍历不为空时
     {
      if(j==-1||*(str+i)==*(str+j)){//回溯到next[0]或者相等时进入if
          i++;j++;     //1.j==-1时,j=0,str[j]再与str[i]比较,相等则next[i]=j,否则next[i]=next[j]
         if(str[i]!=str[j])  next[i]=j;//后移后如果此次相等,那么在和主串匹配不相等时,跳转next数组有两种情况
          else    next[i]=next[j];//1.跳转后相等,那么此过程是多余,此处的值等于跳转之前的值,肯定不匹配,在此优化继续回溯next
                         }//后移不相等的,就有可能和主串匹配上,后移的值不等于刚才的值,那么就有可能等于主串此处的值
       else j=next[j];//不相等时回溯
     }

 }
  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值