算法 字符串模式匹配KMP

定位字符串P在字符串S中的位置,可以称作
字符串的模式匹配

最简单最容易想到的匹配算法是  O(M*N)

//int search(char const*, int, char const*, int)  
//查找出模式串patn在主串src中第一次出现的位置  
//plen为模式串的长度  
//返回patn在src中出现的位置,当src中并没有patn时,返回-1  
int search(char const* src, int slen, char const* patn, int plen)  
{  
    int i = 0, j = 0;  
    while( i < slen && j < plen )  
    {  
        if( src[i] == patn[j] )  //如果相同,则两者++,继续比较  
        {  
            ++i;      
            ++j;             
        }  
        else  
        {  
            //否则,指针回溯,重新开始匹配  
            i = i - (j - 1);  //退回到最开始时比较的位置  
            j = 0;  
        }  
    }  
    if( j >= plen )  
        return i - plen;  //如果字符串相同的长度大于模式串的长度,则匹配成功  
    else  
        return -1;  
}  

KMP算法不需要回溯主串,只考虑模式串,O(M+N)

//代码2-1  
//int kmp_seach(char const*, int, char const*, int, int const*, int pos)  KMP模式匹配函数  
//输入:src, slen主串  
//输入:patn, plen模式串  
//输入:nextval KMP算法中的next函数值数组  
int kmp_search(char const* src, int slen, char const* patn, int plen, int const* nextval, int pos)  
{  
    int i = pos;  
    int j = 0;  
    while ( i < slen && j < plen )  
    {  
        if( j == -1 || src[i] == patn[j] )  
        {  
            ++i;  
            ++j;   //匹配成功,就++,继续比较。  
        }  
        else  
        {  
            j = nextval[j];            
            //当在j处,P[j]与S[i]匹配失败的时候直接用patn[nextval[j]]继续与S[i]比较,  
            //所以,Kmp算法的关键之处就在于怎么求这个值拉,  
            //即匹配失效后下一次匹配的位置。下面,具体阐述。  
        }  
    }  
    if( j >= plen )  
        return i-plen;  
    else  
        return -1;  
}     

模式串的next[]数组计算方法:用KMP算法,模式串与自身作比较

void get_next(char const* ptrn, int plen, int* nextval)  
{  
    int i = 0;   
    nextval[i] = -1;  
    int j = -1;  
    while( i < plen-1 )  
    {  
        if( j == -1 || ptrn[i] == ptrn[j] )    //循环的if部分  
        {  
            ++i;  
            ++j;  
            nextval[i] = j;  
        }  
        else                         //循环的else部分  
            j = nextval[j];             //递推  
    }  
}  

next[]数组的改进计算方法:

void get_nextval(char const* ptrn, int plen, int* nextval)  
{  
    int i = 0;   
    nextval[i] = -1;  
    int j = -1;  
    while( i < plen-1 )  
    {  
        if( j == -1 || ptrn[i] == ptrn[j] )   //循环的if部分  
        {  
            ++i;  
            ++j;  
            //修正的地方就发生下面这4行  
            if( ptrn[i] != ptrn[j] ) //++i,++j之后,再次判断ptrn[i]与ptrn[j]的关系  
                nextval[i] = j;      //之前的错误解法就在于整个判断只有这一句。  
            else  
                nextval[i] = nextval[j];  
        }  
        else                                 //循环的else部分  
            j = nextval[j];  
    }  
}  
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/jerryzcx/article/details/19694063
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞