KMP模式匹配算法

KMP算法
定义:
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
原理:
如果主串S=“abcdefgab”,要匹配的T=“abcdex”,对T来说,“abcdex”首字母“a”与后面的串“bcdex”中任意一个字符都不相等。也就是说,既然“a”不与自己后面的子串中任何一字符相等,那么主串与子串前5个字符相等,意味着子串T的首字符“a”不可能与S串的第2位到第5位的字符相等,就不需要匹配第2到第5位的字符。
T串各个位置的j值的变化定义为一个数组next.
当j=1时,next[j]=0
当此集合不空时,Max{k|1<k<j,且‘p1…pk-1’=‘pj-k+1…pj-1’}
其他情况,next[j]=1.
next数组值推导:
1.T=“abcdef”

j123456
Tabcdex
next[j]011111

1).当j=1时,next[1]=0;
2).当j=2时,j由1到j-1就只有字符“a”,属于其他情况next[2]=1;
3).当j=3时,j由1到j-1是“ab”,"a"与“b”不相等,属于其他情况next[3]=1;
4).以后同理,所以T串的next[j]为011111.

2.T=“abcabx”

j123456
Tabcabx
next[j]011123

1).当j=1时,next[1]=0;
2).当j=2时,j由1到j-1就只有字符“a”,属于其他情况next[2]=1;
3).当j=3时,j由1到j-1是“ab”,"a"与“b”不相等,属于其他情况next[3]=1;
4).当j=4时,同上,next[4]=1;
5).当j=5时,此时j由1到j-1是“abca”,前缀字符“a”与后缀字符“a”相等,因此可推算出k值为2,因此next[5]=2;
6).当j=6时,此时j由1到j-1是“abcab”,前缀字符“ab”与后缀字符“ab”相等,因此可推算出k值为3,因此next[6]=3;
代码

/*通过计算返回子串T的next数组。*/
void get_next(String T,int *next)
{
    int i=1,j=0;
    next[1]=0;
    while(i<T[0])/*此处T[0]表示串T的长度*/
    {
        if(j==0||T[i]==T[j])/*T[i]表示后缀的单个字符*/
        {                   /*T[j]表示前缀的单个字符*/
           ++i;
           ++j;
           next[i]=j;
        }
        else
           j=next[j];/*若字符不相同,则j值回溯*/
    }
}

/*返回子串T在主串中第m个字符之后的位置。若不存在,则函数返回0.*/
/*T非空,1<=m<=Strlength(S)*/
void get_next(String T,int *next)
{
    int i=1,j=0;
    next[1]=0;
    while(i<T[0])/*此处T[0]表示串T的长度*/
    {
        if(j==0||T[i]==T[j])/*T[i]表示后缀的单个字符*/
        {
            /*T[j]表示前缀的单个字符*/
            ++i;
            ++j;
            next[i]=j;
        }
        else
            j=next[j];/*若字符不相同,则j值回溯*/
    }
}
int Index_KMP(String S,String T,int m)
{
    int i=m,j=1;
    int next[255];
    get_next(T,next);/*对串T分析,得到next数组*/
    while(i<=S[0]&&j<=T[0])
    {
        if(j==0||S[i]==T[i])/*两字母相等则继续*/
        {
            ++i;
            ++j;
        }
        else
            j=next[j];
    }
    if(j>T[0])
        return i-T[0];
    else
        return 0;

}

KMP模式匹配算法改进

对next函数改良

/*求模式串T的next函数修正值并存入nextval*/
void get_nextval(String T,int *nextval)
{
    int i=1,j=0;
    nextval[1]=0;
    while(i<T[0])/*此处T[0]表示串T的长度*/
    {
        if(j==0||T[i]==T[j])/*T[i]表示后缀的单个字符*/
        {
            /*T[j]表示前缀的单个字符*/
            ++i;
            ++j;
            if(T[i]!=T[j])    /*若当前字符与前缀字符不同*/
                nextval[i]=j;  /*则当前的j为nextval在i位置的值*/
        }
        else
            nextval[i]=nextval[j];/*如果与前缀字符相同,则将前缀字符的nextval值赋值给nexxtval在i位置的值*/
        else
            j=nextval[j]/*若字符不相同,则j值回溯*/
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值