kmp算法

这个算法通常用来解决B是否是A的子串,也比较有局限性。
看了一晚上解释我终于明白了。
很短,很好写,很好理解。
定义一些东西
A:一个串
B:另一个串
j:a[i-j+1…..i]=b[1…j] 随着i的变化而变化,但与i的取值无关,用更通俗的话来讲,就是已经匹配了多少位。
P[i]:b[1…p[i]]=b[j-p[i]+1…..j],有没有发现与上面非常相似,就是前p[i]位与后p[i]位相等。
先列个数据(实在找不到好的数据,就copy了别人的一个数据)
A:a b a b a b a a b a b
B:a b a b a c b
这时对于B来说,P数组的值为[0,0,1,2,3,0,0]
然后我们惊奇地发现,在第6个位置炸了,无法匹配,所以要找新的,怎么找呢,我们有P数组,所以用P[5],p[5]=3,取后三位,可以转换后接着找。
A:a b a b a b a a b a b
B:…..a b a b a c b
这时我们惊奇地发现,在第六个位置是可以的
但这时候在第7个位置还是不行,再转换,因为j=4,所以p[4]=2
A:a b a b a b a a b a b
B:………a b a b a c b
尽管我们很努力,但事实证明这不能匹配,不过从中我们可以观察到kmp的匹配过程——
逐位匹配,不行就换。很清晰,很明了。

        for i:=1 to length(a)do
        begin
                while(j>0)and(a[i]<>b[j+1])do j:=p[j];
                if(a[i]=b[j+1])then inc(j);
                if(j=length(b))then
                begin
                        writeln('YES');
                        halt;
                end;
        end;
        writeln('NO')

我们遗留了一个问题,就是P数组怎么求
显然这个P数组求的过程与我们正式匹配的过程非常相似,对吧。
机智的你应该会发现,P就是b串自我匹配

        for i:=2 to length(b) do
        begin
                while(j>0)and(b[i]<>b[j+1])do j:=p[j];
                if(b[i]=b[j+1])then inc(j);
                p[i]:=j;
        end;

想象一下,写写数据,脑补一下过程。
其实我一开始也不明白的,后来拿着程序跑一个数据,一步一步跑,就慢慢理解了。
学算法,不一定要快,就算比别人慢,只要学会了,都是一样的。
可能有人会有疑问
为什么P可以用来转换位置后接着匹配?
假设当前 a[i-j+1…..i]=b[1…j]
P数组它表示的前p[j]位与后p[j]位相等,也就是说a[i-j+1…i]这个区间的前p[j]与后p[j]位也相等,
感性理解一下,就是转换成a的后p[i]位与b的前p[i]位匹配,对吧?所以这就很明显了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值