kmp算法

来源:互联网 发布:博奥预算软件 编辑:程序博客网 时间:2024/05/01 01:01
  昨天在网上找了很多的精确匹配算法,包括从前开始扫描的kmp算法,还有从后开始匹配的br算法,还有从中间向俩边匹配的LDM算法,我还是比较喜欢KMP算法,它是一种最差线性匹配算法。

   一般的模式匹配算法的时间复杂度为o(n+m),n为母串长度,m为模式长度,实现很简单(环境linux anjuta)
int  normalStrMatch ( char  * parent , char * sun )
{
     int i = 0 , j = 0 ;
    while (  parent[i+j]  != '/0' &&  sun[j] != '/0' ) //the lase location
    {
        if  ( parent[i+j] == sun[j])
        {
            j ++ ;
        }
        else
        {
            j = 0 ;
            i ++ ;
        }
    }
    if ( sun[ j ] == '/0' )
        return  i ;
    else
        return -1 ;   
}
kmp算法较这种算法的有点在于对模式字符串和母串的回溯上,它不象一般匹配算法,当有 不匹配的时候,母串后移1,而模式串回溯到开始,kmp算法记忆已匹配信息,继续匹配。
kmp算法的关键在于next函数的,next[j]的含义是在第j个字符上不匹配,下一次匹配开始的位置。
实现:
//Get the next function according to sun string
void  getNextVal ( char * sun , int * next )
{
    int i = 0 , j = -1 ;
    next[ i] =  0 ;
    while ( sun[i] != '/0' )  // i is smaller than the length of sun string
    {
        if ( j == -1 || sun[i] == sun[j] )
        {
            i ++ ;
            j ++ ;
            next[i] = j + 1 ;
        }
       else
          j = next[j]  - 1 ;         
    }   
}
有了next函数后,匹配和一般模式算法相似,只是模式串的回溯不是到1而是到next[j]
// the kmp String Matching Algorithm
int kmpStrMatch ( char * parent , char * sun )
{
    int i = 0 ,j = 0 ;
    while (( parent[i] != '/0' && sun[j] != '/0') || j == -1  )
    {
        if ( j == -1 ||  parent[i] == sun[j])
        {
            i ++ ;
            j ++ ;
        }
        else
            j = next[j] - 1 ;
    }
    if ( sun[j] == '/0')
        return  i ;
    else
        return -1 ;
       
    }
整个算法的时间复杂度为o(n+M)
所有代码都调试通过,实验环境(ubuntu Anjuta )