KMP算法

   看算法过程总有个经历,每次都以为自己真正理解了,隔一段时间看,发现自己并没有理解地那么透彻。kmp算法是大二时学的,这次复习数据结构重新看了一下,用简单到复杂的思路,将这个算法过程贴下。下面以goodgoodstudy这个字符串为例。

假设我要在一篇文章找"goodgoodstudy",首先最容易想到的模式匹配算法是:

算法1:

int  foo( string foo  , string bar , int pos )
{
     string::size_type i = pos , j = 0 ;
     while ( i < foo.size() && j < bar.size() )
     {
          if ( foo[i] == bar[j] )
          {
               i++ , j++ ;
          }
          else
          {
              i  = i - j ;           // 退回
              j  = 0     ;           // 子串游标为0
          }
     }
     if ( j > bar.size()){
         return i-j ;
     }
     else
         return -1  ;
  
}

这个算法简单,但也有用,可以快速写出程序,用来验证其他复杂算法的正确性。kmp算法利用先前比较的结果,而不必回退主串的游标。kmp增加了一个next[]数组,如果将算法1也看成next[]数组,由于每次不匹配时,子字符串回退到1,那么字符串"goodgoodstudy"的next[]为13个1。

但是为什么kmp算法中next[1]=0,而不是1?
因为每次kmp算法不匹配时,根据next[ ... next[] .. ] 这样一直回溯时,若回溯到起点时,如果next[1]=1,则会陷入一个死循环,故next[1]=0,可以终止循环。

kmp算法:

int  kmp( string foo  , string bar , int pos )
{
     string::size_type i = pos , j = 0 ;
     j--;                        //从0开始
     while ( i < foo.size() && j < bar.size() )
     {
          if ( (j == -1 ) || (foo[i] == bar[j])  )     //这里string字符下标从0开始 故终止选-1
          {
               i++ , j++ ;
          }
          else
          {
                                                        //  i  = i - j ;          
                j  = next[j]                ;           // 子串游标为0
          }
     }
     if ( j > bar.size()){
         return i-j ;
     }
     else
         return -1  ;
  
}

问题二:怎么求next[]数组?

这其实是一个同类型的问题,next[0]=-1,那么next[1]呢,使用next[1]时表示主串和子串没有匹配,这时字符串foo[1]和foo[0]]若相等,则next[1] =next[0]+1=0。同理比较到子串k,则可以求出next[k],那么next[k+1],若foo[k+1]与next[k]相等,则next[k+1]=next[k]+1,否则next[k+1]则要继续与next[  next[]  ] 比较 ,直到next终止。但是可以注意到利用next一次次的迭代计算,最后next值终止,那么我们计算next值可以直接将该值赋-1,从而提前结束迭代。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值