KMP算法理解,and优化(待发)

以前看kmp算法没有重视,如今发现当时的理解存在一些问题。 说kmp算法,先要说一般的匹配算法 一般匹配算法就是以keyword的首字母为标记。匹配过程遇到不匹配,标记移动到下一位,重新与文本串匹配。当keyword只有一个字母时,效率是一样的,但当keyword较长,极端情况是keyword自己本身没有重复字母,匹配过程中遇到文本子串与keyword最后一位不匹配时,我们自己心里清楚,完全没必要让标记只移动一位,可以整个移动keyword(length)-1位

char[]01234567……
textabcdeaab……
keyabcdef

当然这种情况我们心里清楚,下一步完全可以直接比较key[0]和text[5]。


我们希望能将比较过的过程尽量不要重复,利用比较过的结果
当比较到 key[j]!= text[i] 时 说明key[0,j-1]==text[i-j,i-1]。
我们最希望的状态是 j直接回到0继续和text比较。
但当出现 key[0,,k]==key[(j-1)-k,j-1],时,且text[i]==key[k],我们必须从i,k处继续比较,以避免忽视这种匹配。

ii
textabcabcab……
keyabcaba
jj
char[]012345

上表中k为2,
k就是key的子串key[0,j-1]中前后缀相等的最大长度。(因为数组下标从0开始,比较的是相等串的后一个字母,恰恰是key[k])。
abcaba为例

abcaba0,j-1子串的前后缀k
j=0
可以理解成j前面有几个元素
j-1=-1
这就是一些kmp算法设置next[0]=-1的原因
0
j=1a0
j=2ab0
j=3abc0
j=4abca1
j=5abcab2

kmp算法中next[j] 就是key[j]对应的k。next的值可以通过key[]的自我比较来确定,如果已知next[i]=k,即必有key[0,k]==key[i-k,i],则当key[i+1]=key[k+1]时,next[i+1]=k+1;否则找key[0,k]内的重复子串,此时可比较key[next[k]]==key[i+1] (相当于使用已知next[]搜索,跟kmp思想是一样的)。
于是就有kmp算法

//kmp主体,本代码只体现思想,并不考虑应用场景
int KMP(Str text,Str key,int next[])
{
    int i=0,j=0;
    while(i<text.length && j<key.length)
    {
        if(text.ch[i]==key.ch[j])
        {++i;++j;}
        else
        {
            j=next[j];
            if(j==0)++i;
        }
    }
    if(j>=key.length)
        return i-key.length;//若继续搜索可以把结果先存入数组
    else return -1;
}
//生成next数组
void getnext(Str key,int next[])
{
    int i=1,k=0;
    next[0]=0;//初始化
    next[1]=0;
    while(i<key.length)
    {
        if(key[i]==key[k])
        {
            next[++i]=++k;//next[i+1]=k+1
        }
        else
            k=next[k];//回溯对比key[next[k]]?=key[i]
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值