算法笔记——KMP算法

 算法思路

用i来标记S主串匹配位置,j来标记T子串匹配位置,采用i不回退,j回退到nxt[j]位置的方式降低匹配时间。

其中,nxt[j]数组表示在j位置匹配失败最优的回退位置,即S[0]~S[i-1]在T[0]~T[j-1]之间除了当前串最长的匹配子串的位置

 求nxt数组

nxt数组实际上就是T的前缀与S后缀的最长匹配长度,由于匹配过程中S[i-j]~S[i-1]与T[0]~T[j-1]完全相等,因此只需要搜索T的子串T'(T[0]~T[j-1])中前缀和后缀相等的最大长度即可。

在前缀和后缀相等的最大长度的查找中,利用递推思想简化复杂度

假设已经知道nxt[j]=k

①如果T[j]==T[k](注意,处理到某个位置时代表的是前面的位置相等,当前位置不一定相等)

显然nxt[j+1]=k+1

②如果T[j]!=T[k]

k=nxt[k]

nxt[k]相当于直接跳到了上一个与当前已匹配子串相同的位置,直到T[j]==T[k]为止

void get_nxt(string t)
{
    int j=0,k=-1,tlen=t.length();
    nxt[0]=-1;//初始化
    while(j<tlen)
    {
        if(k==-1 || t[k]==t[j])//k==-1一定要写前面不然会下标越界
            nxt[++j]=++k;
        else
            k=nxt[k];
    }
}

int KMP(string s,string t,int pos)
{
    int slen=s.length();
    int tlen=t.length();
    int i=pos,j=0;
    while(i<slen && j<tlen)
    {
        if(j==-1 || s[i]==t[j])
            i++,j++;
        else
            j=nxt[j];
    }
    if(j>=tlen)    return i-tlen+1;
    else return -1;
}

第①步有一个优化

如果T[j+1]==T[k+1]

那么nxt[j+1]=nxt[k+1]

因为如果T[j+1]==T[k+1]那么这一次回跳的比较肯定是失败的,因此直接跳到下一个位置

该优化不降低复杂度级数,仍为O(n+m),但减少了一定的比较次数。

void get_nxt(string t)
{
    int j=0,k=-1,tlen=t.length();
    nxt[0]=-1;//初始化
    while(j<tlen)
    {
        if(k==-1 || t[k]==t[j])//k==-1一定要写前面不然会下标越界
        {
            if(t[++j]==t[++k])
                nxt[j]=nxt[k];
            else nxt[j]=k;
        }    
        else
            k=nxt[k];
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值