详解KMP算法

注:最近刷题刷到KMP算法,大致印象还有但是细节有些遗忘了,因此特地回顾了大一下学期数据结构所学的内容,在此进行一下记录。

 

一、模式匹配

KMP算法解决的的问题是模式匹配,也就是子串定位,是串处理中最重要的运算之一,具体任务描述如下:

假设有一个主串S=“a1a2...an”, 子串T=“b1b2...bm”(m<<n),子串定位则是在主串中找到子串出现的位置。若S中没有模式为T的子串,返回值为零,称为匹配失败。

 

二、模式匹配的经典算法

记主串为S,子串为T。从i=1, j=1开始匹配,若匹配成功(S[i]==T[j]),则i,j分别向后移动一位;若匹配失败,j退回1,i退回i-j+2,再重新开始匹配,如下图所示:

 

具体算法如下:

int Index(String S, String T, int pos)
{
    int i=pos, j=1;
    while(i<=S[0]&&j<=T[0]){
        if(S[i]==T[j]) i++,j++;
        else i=i-j+2, j=1;    //指针回溯
    }
    if(j>T[0]) return i-T[0];    //匹配成功
    return 0;    //匹配失败

}

因此最好的时间复杂度为O(m+n),最坏的时间复杂度为O(m*n).

 

三、KMP

经过观察发现当每次匹配失败之后,不需要将指针i回溯,也不需要一个一个地移动j指针,因为字符串存在一些特征,当前位置匹配失败之后如果按照最传统的方法直接后移一位的话,下一步匹配还是会失败,造成了计算资源的浪费,因此提出了KMP算法。其中指针i始终是往前走的,此外还需要保留一个next数组来判断在当前位置j匹配失败后应该移动到的位置next[j]。大致的过程如下图所示:

1、具体算法如下:

int Index_KMP(String S, String T, int pos){
    int i=pos, j=1;
    while(i<S[0]&&j<=T[0]){
        if(j==0||S[i]==T[j]) i++,j++;
        else j=next[j];    //不止向后移动一位,而是移动j-next[j]+1位
    }
    if(j>T[0]) return i-T[0];    //匹配成功
    else 
        return 0;
}

2、子串next数组的求解

next数组的求解主要是与子串T[1...j-1]前后缀相同子串的长度有关,如果next[j]=k,则T[1..k-1] == T[j-k+1..j-1]T[1..k-1] == T[j-k+1],因此得到如下求解公式:

具体代码如下:

void get_next(String T, int next[])
{
    j=1, next[1]=0, k=0;
    while(j<T[0]){
        if(k==0||T[j]==T[k]){j++;k++;next[j]=k;}
        else{k=next[k]}
    }
}

 

 

3、进一步改进

可能会存在这样的情况,T[j]=T[next[j]],这样如果是在T[j]处失配移动到T[next[j]]处依然会失配,因此提出如下改进方案:

void get_nextval(String T, int nextval[])
{   // 求模式串T的next函数修正值并存入数组nextval
      j = 1; nextval[1] = 0; k = 0;
      while (j < T[0])
      {
          if (k == 0 || T[j] == T[k])
          {
              ++j;  ++k;
              if (T[j] != T[k])  nextval[j] = k;
              else  nextval[j] = nextval[k];
         }
        else
           k = nextval[k];
      }
} 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值