kmp算法初步了解

最近一直在看kmp算法来解决字符串匹配的超时问题,看了好多材料终于有一点顿悟了。其实kmp算法难就难在对于next[]数组的理解方面,有很多人不理解不匹配的字符对应的模式函数值next[i]的值是怎么得来的,总结起来解释就是找出不匹配字符前面与开头字符的最大匹配数字。例如在求解模式串T:ababc时其第五个字符前面两个字符与开头两个字符一致,故next[4]=2.除此之外对于其他几种情况有以下总结:

(1)next[0]= -1 意义:任何串的第一个字符的模式值规定为-1。

(2)next[j]= -1   意义:模式串T中下标为j的字符,如果与首字符

相同,且j的前面的1—k个字符与开头的1—k

个字符不等(或者相等但T[k]==T[j])(1≤k<j)。

如:T=”abCabCad” 则 next[6]=-1,因T[3]=T[6]

(3)next[j]=k    意义:模式串T中下标为j的字符,如果j的前面k个

字符与开头的k个字符相等,且T[j] != T[k] (1≤k<j)。

                       即T[0]T[1]T[2]。。。T[k-1]==

T[j-k]T[j-k+1]T[j-k+2]…T[j-1]

且T[j] != T[k].(1≤k<j);

(4) next[j]=0   意义:除(1)(2)(3)的其他情况。

 

 

对于kmp算法而言,第一个难点就是找出模式串的模式函数值,其一般代码抄写如下:

void get_next()
{   
     int i = 0, j = -1;   
     next[0] = -1;    //赋值字符差串的首个模式函数值为-1;
    while(i < lenp)//lenp为模式串的长度   
{         
if(j == -1 || pat[i] == pat[j])//找出模式串中每个字符的模式函数值 {              i ++; j ++;              next[i] = j;          }         else j = next[j];     } }

接下来要做的工作是开始于模板串进行匹配,对于匹配的方法,却别于传统可能TLE的代码而言最大的优势就是不用回溯,从而使复杂度降至O(m+n)而不是O(m*n),kmp的关键是在匹配不成功时调用模式函数值,而不是进行回溯到初始位置进行调用。其代码抄写如下:

int KMP()
{  
  int i = 0, j = 0;    
get_next();    
while(i < lent && j < lenp)//lent为模版串的长度,其中模版串为text,模式串为pat
{     
   if(j == -1 || text[i] == pat[j])
{           
 i ++; j ++;       
 }     
   else j = next[j];   
 }   
 if(j >= lenp) return i - lenp;  
  else return -1;
}

关于 kmp最近只有初步的理解,大多数还是死记硬背的成分,相信写会代码,练习练习也就掌握了。

posted on 2013-08-31 20:31  金仁赫  阅读(208)  评论(0)    收藏  举报

导航