第一次学习kmp可能会有的疑惑

上个星期刚复习完kmp,感觉一段时间不写就又生疏了

链接:

【模板】KMP - 洛谷

理解部分(无码)

最长相同(公共)子串//border

这个名词有点拗口,但是已经精准地道出了border的性质:

最长--目前最长的、相同--从左往右完全相同、子串--来自同一段字符串的子串

理解kmp的第一步就是理解这个最长公共子串是什么

值得注意的是,比较前后缀的时候,中间部分不必严格对称。

ABCABC//前后缀最长相同值为3
ABCBDEWAB//前后缀最长相同值为2(中间没影响最后的比较)

next数组(也叫border数组)

在不同风格的解法中,next数组是不同的。我们这里为避免混淆,只推荐最经典泛用的数组。

即:下标从0开始,且下标代表最长公共前后缀的长度。

next的构建,其实与两字符串的比较大同小异。说白了,题目要求的是两个字符串的比较,next的构建过程就是自己和自己比较。

不过对于新手来说,独立构建next数组难度略大,很多细节如条件判断的顺序,比较难安排

代码部分

next/border 创建:

string s2;//被比较的小子串
int size=s2.size();
int next[size]={0};
for(int i=1,j=0;i<size;++i)//i在右面,而且永远右移,而j经常回退
{
    while(j&&s2[i]!=s2[j]){
        j=next[j-1];   //这个回退新手能拿捏住吗?
    }
    if(s2[i]==s2[j])
    ++j;//匹配成功则j右移
    
    next[i]=j;
}

比较s1,s2:

string s1;
int size=s1.size();
for(int i=0,j=0;i<Len1;++i){//这里就要从0开始了,因为每一位都要比较。
        while(j&&s1[i]!=s2[j]){
            j=border[j-1];
        }
        if(s1[i]==s2[j]){
            ++j;
        }
        if(j==size){
            cout<<i+2-j<<endl;
            
        }//大同小异

如果你已经比较深入了解这种算法,应该会了然两段代码其实有着相同的本质

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monster_Prince

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值